首页 > 其他分享 >TIM + DMA + ADC

TIM + DMA + ADC

时间:2023-02-18 01:22:04浏览次数:29  
标签:DMA void FFT MagBuffer TIM ADC def

#include "public.h"

#define FFT_POINT 	(256)

static uint16_t _DmaBuffer[FFT_POINT];
static uint16_t _AdcBuffer[FFT_POINT];
static uint8_t F_DMA_TC;

static int32_t FFT_InBuffer[FFT_POINT];
static int32_t FFT_OutBuffer[FFT_POINT];
#define FFT_MagBuffer _AdcBuffer


static void _InitClk(void) {
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,   ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,   ENABLE);
}

static void _InitGpio(void) {
	SocGpio_SetMode(SocGpio_GetPinIndex(0<<4|1), INPUT_MODE_AIN);
	SocGpio_SetMode(SocGpio_GetPinIndex(0<<4|0), OUTPUT_MODE_PUSH_PULL);
}

static void _InitDMA(void) {
	DMA_InitTypeDef 	def;
	
	// 初始化
	def.DMA_PeripheralBaseAddr 	= (uint32_t)(&ADC1->DR); 								// 外设地址
	def.DMA_MemoryBaseAddr 		= (uint32_t)(&_DmaBuffer[0]); 							// 内存地址
	def.DMA_DIR 				= DMA_DIR_PeripheralSRC; 								// 从外设复制到内存
	def.DMA_BufferSize			= ASIZE(_DmaBuffer);									// 内存元素个数
	def.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;							// 外设地址固定
	def.DMA_MemoryInc 			= DMA_MemoryInc_Enable;									// 内存地址递增
	def.DMA_PeripheralDataSize 	= DMA_PeripheralDataSize_HalfWord;						// 外设元素大小16字节
	def.DMA_MemoryDataSize 		= DMA_MemoryDataSize_HalfWord;							// 内存元素大小16字节
	def.DMA_Mode 				= DMA_Mode_Circular;									// 循环采集 
	def.DMA_Priority 			= DMA_Priority_High; 									// 循环
	def.DMA_M2M 				= DMA_M2M_Disable;										// 外设到内存
	DMA_Init(DMA1_Channel1, &def);	
	
	// 中断
	NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
	NVIC_EnableIRQ(DMA1_Channel1_IRQn);
	DMA_ClearFlag(DMA1_FLAG_TC1);
	DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
	
	DMA_Cmd(DMA1_Channel1, ENABLE);
}


static void _InitAdc(void) {
	ADC_InitTypeDef 	def;
	
	// 初始化
	ADC_StructInit(&def);	
	def.ADC_Mode              	= ADC_Mode_Independent;  	// 独立模式 
	def.ADC_ScanConvMode      	= DISABLE;      			// 单通道 
	def.ADC_ContinuousConvMode 	= DISABLE;      			// 定时器触发,不连续转换
	def.ADC_ExternalTrigConv  	= ADC_ExternalTrigConv_T3_TRGO;// 转换不受外界决定 
	def.ADC_DataAlign         	= ADC_DataAlign_Right;   	// 右对齐 
	def.ADC_NbrOfChannel     	= 1;       					// 扫描通道数 	
	ADC_Init(ADC1, &def);
	
	// 通道
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_1Cycles5);
	ADC_DMACmd(ADC1, ENABLE);	
	
	ADC_Cmd(ADC1, ENABLE);	
	
	// 校准
	ADC_ResetCalibration(ADC1);	
	while(ADC_GetResetCalibrationStatus(ADC1));
	
	ADC_StartCalibration(ADC1);	
	while (ADC_GetCalibrationStatus(ADC1));
	
}

static void _InitTim(void) {
	TIM_TimeBaseInitTypeDef   def;
	TIM_TimeBaseStructInit(&def); 
	
	def.TIM_Period 			= 100-1;
	def.TIM_Prescaler 		= 72-1;
	def.TIM_ClockDivision 	= TIM_CKD_DIV1;
	def.TIM_CounterMode 	= TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM3, &def);
	
	TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
	
	TIM_Cmd(TIM3, ENABLE);
}

void cr4_fft_256_stm32(void *pssOUT, void *pssIN, u16 Nbin);

static void _FFT_Proc(void) {
	for (uint16_t i = 0; i < FFT_POINT; i++) {
		FFT_InBuffer[i] = (_AdcBuffer[i]-1990) << 16;
	}	
#if 0	
	printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
			FFT_InBuffer[1], FFT_InBuffer[2], FFT_InBuffer[3], FFT_InBuffer[4], 
			FFT_InBuffer[5], FFT_InBuffer[6], FFT_InBuffer[7], FFT_InBuffer[8], 
			FFT_InBuffer[9], FFT_InBuffer[10], FFT_InBuffer[11], FFT_InBuffer[12]); 
#endif	
	cr4_fft_256_stm32(FFT_OutBuffer, FFT_InBuffer, FFT_POINT);
	
#if 0	
	printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
			_AdcBuffer[1], _AdcBuffer[2], _AdcBuffer[3], _AdcBuffer[4], 
			_AdcBuffer[5], _AdcBuffer[6], _AdcBuffer[7], _AdcBuffer[8], 
			_AdcBuffer[9], _AdcBuffer[10], _AdcBuffer[11], _AdcBuffer[12]); 
#endif
}

#if 0
void GetPowerMag(void)
{
    signed short lX,lY;
    float X,Y,Mag;
    unsigned short i;
	
    for(i=0; i<NPT; i++)
    {
        lX  = (lBufOutArray[i] << 16) >> 16;
        lY  = (lBufOutArray[i] >> 16);
			
				//除以32768再乘65536是为了符合浮点数计算规律
        X = NPT * ((float)lX) / 32768;
        Y = NPT * ((float)lY) / 32768;
        Mag = sqrt(X * X + Y * Y)*1.0/ NPT;
        if(i == 0)	
            lBufMagArray[i] = (unsigned long)(Mag * 32768);
        else
            lBufMagArray[i] = (unsigned long)(Mag * 65536);
    }
}
#endif

static void _Send(uint8_t ch) {
	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
	USART_SendData(USART1, ch);
}

// STEP:39Hz
static void _FFT_GetMag(void) {
	int16_t x, y;	
	for (uint16_t i = 1; i <= 64; i++) {
		x = FFT_OutBuffer[i]&0xFFFF;
		y = FFT_OutBuffer[i]>>16;
		//printf("%d: %d, %d\n", i, x, y);
		FFT_MagBuffer[i] = sqrt(x*x + y*y);		// 存在超过25为有信号, 需要连续好几个周期的判断,以便防抖
	}
}

void SocAdc_Init(void) {
	_InitClk();
	_InitGpio();
	_InitDMA();
	_InitAdc();
	_InitTim();
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}


void SocAdc_Main(void) {
	if (F_DMA_TC) {
		F_DMA_TC = 0;
		memcpy(_AdcBuffer, _DmaBuffer, sizeof(_DmaBuffer));
		GPIOA->BSRR = GPIO_Pin_0;
		ADC_SoftwareStartConvCmd(ADC1, ENABLE);			
		_FFT_Proc();
		_FFT_GetMag();
		
		#if 1		
		_Send(0xFF);
		for (uint16_t i = 1; i <= 64; i++) {	// 不要第一个分量
			if (FFT_MagBuffer[i] > 0xFE) {
				_Send(0xFE);
			} else {
				_Send(FFT_MagBuffer[i]);
			}
		}		
		#endif
		
		#if 0
		printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
			FFT_MagBuffer[1], FFT_MagBuffer[2], FFT_MagBuffer[3], FFT_MagBuffer[4], 
			FFT_MagBuffer[5], FFT_MagBuffer[6], FFT_MagBuffer[7], FFT_MagBuffer[8], 
			FFT_MagBuffer[9], FFT_MagBuffer[10], FFT_MagBuffer[11], FFT_MagBuffer[12]); 
		#endif
	}
}


// DMA的ADC通道中断
void DMA1_Channel1_IRQHandler(void) {	
	if (DMA_GetFlagStatus(DMA1_FLAG_TC1)) {
		DMA_ClearFlag(DMA1_FLAG_TC1);		
		ADC_SoftwareStartConvCmd(ADC1, DISABLE);		
		F_DMA_TC = 1;
		GPIOA->BRR = GPIO_Pin_0;
	}
}

 

标签:DMA,void,FFT,MagBuffer,TIM,ADC,def
From: https://www.cnblogs.com/kehuadong/p/17131878.html

相关文章