更新
后续在实验过程中发现ADC采集的数据很多时候都是不准的,分析发现原因是当我想要在ADC_BUFFER中进行取平均求值的时候,ADC_BUFFER中的数据仍在进行转换,这样在测量动态数据的时候ADC取平均返回的数据就不准了,解决办法是在要取ADC值之前关闭DMA传输,取值后再开启DMA传输。
引言
最近想用在单片机上实现DFT并在屏幕上显示波形,之前的想法是定时器中断计时,软件触发ADC,采集到一定数量的点数后计算一次DFT,然后在屏幕上画出波形,由于DFT需要的采样点数比波形的点数少,结果发现在DFT点数之后会丢失十几个数据,认为是DFT的计算时间太长了,在DFT计算过程中的这段数据就没法进行软件触发采样而导致丢失。
因此想直接用定时器触发ADC-DMA模式,这样所有的AD转换过程都不用通过CPU,就不存在因DFT计算时间长导致采样不连续的问题了。
一、定时器设置
定时器采用TIM3,同时开启中断和更新时间触发。中断是用来计时的,这里我的采样频率是1kHz,中断是1ms触发一次
u16 ms = 0; //ms计时
void TIM3_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef Tim3;
NVIC_InitTypeDef NVIC_Tim;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 ,ENABLE);
Tim3.TIM_Period = arr;
Tim3.TIM_CounterMode = TIM_CounterMode_Up ;
Tim3.TIM_Prescaler = psc;
Tim3.TIM_ClockDivision = TIM_CKD_DIV1 ;
TIM_TimeBaseInit(TIM3,&Tim3);
TIM_ITConfig(TIM3,TIM_IT_Update ,ENABLE );//允许更新中断
NVIC_Tim .NVIC_IRQChannel = TIM3_IRQn ;
NVIC_Tim .NVIC_IRQChannelPreemptionPriority = 0;
NVIC_Tim .NVIC_IRQChannelSubPriority = 0;
NVIC_Tim .NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_Tim);
TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update);//配合ADC用Tim3TRGO触发
TIM_Cmd(TIM3,ENABLE);
}
//中断函数
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
ms++;
}
}
二、DMA设置
因为ADC是定时器连续转换,DMA应该设置成循环模式,从外设到内存,内存地址自增,外设地址不自增
通过查看stm32F4的数据手册可以看到ADC都在DMA2上,这里我用的是ADC1,有