其他分享
首页 > 其他分享> > 基于stm32F407ZGT6的三重ADC交替采样+DMA传输数据+定时器TRGO触发

基于stm32F407ZGT6的三重ADC交替采样+DMA传输数据+定时器TRGO触发

作者:互联网

好久没写博客了,最近挺忙的。近来有些好玩的实现,网上的资料并不是非常详细,打算慢慢写下来,希望别人能少走一点弯路。 因为希望提高ADC的采样率,这次我试着实现了一下三重ADC交替采样+DMA搬运至内存+TIM的TRGO触发采样(环境是stm32cubemx 6.5.0和keil 5) 

首先打开cubemx进行基础设置(设置时钟树,RCC,SYS)

然后设置ADC1(下图为具体设置,仅供参考)

此处我们将ADC_Mode设置为Triple regular simultaneous mode only,并打开DMA连续请求(为了使DMA能够填满数组,按照我们的预期工作)

外部触发源设置为TIM2的TRGO

由于已经设置了ADC模式,ADC2和ADC3是跟随ADC1的,所以他们的模式是不能改变的,和ADC1一样设置就可以了

接下来我们设置DMA,记住要设置成circular模式,不然他就只会传输一次,选择一次传输Half Word,从外设搬运到内存

主要的设置就这些,串口的初始化已经省略了,后面我们将用串口重定向打印数据至串口(详见我之前的博客串口重定向发送和接收

现在我们只需要生成代码,打开工程

这里有个小细节:DMA和ADC的初始化顺序不能错了,要先初始化DMA再初始化ADC(其实用到DMA传输数据的外设都要在DMA初始化之后再进行初始化,因为不先初始化DMA的话,在初始化其他外设时,当配置到DMA相关的设置时会出现错乱,导致外设无法正常工作,比如ADC就会传输数据失败,但是DMA一直是处于busy状态)

下面我们进行垃圾核心代码的编写

我的初始化顺序(仅供参考)

1 MX_GPIO_Init();
2 MX_DMA_Init();
3 MX_ADC1_Init();
4 MX_ADC2_Init();
5 MX_ADC3_Init();
6 MX_DAC_Init();
7 MX_TIM2_Init();
8 MX_USART1_UART_Init();

主函数当中编写的代码如下:

1 HAL_ADC_Start(&hadc1);
2 HAL_ADC_Start(&hadc2);
3 HAL_ADC_Start(&hadc3);//启动ADC
4 HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t *)ADC_value,3000);
5 HAL_TIM_Base_Start(&htim2);//启动TIM2,用于触发ADC采样

对于数据的处理,我更倾向于写在回调函数里面

1 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
2 {
3   int i;
4   for(i = 0;i < 1000;i++)
5   {
6     printf("%f,%f,%f\n",ADC_value[3 * i] * 3 / 4096.0,ADC_value[3 * i + 1] * 3 / 4096.0,ADC_value[3 * i + 2] * 3 / 4096.0);
7   }
8   return;
9 }

我们再编译,烧录程序。 至此,我们就可以实现ADC三重交替采样了

 /*------------------------------------------------------------------------分割线------------------------------------------------------------------------*/

我思来想去感觉还是在回调函数里面改变一个标志位就可以了,把这么一大段处理放进去不太好,容易出现中断嵌套等我们不希望出现的现象

尽量把处理的步骤写到函数里面去执行,只需通过判断标志位即可达到同等效果

标签:DMA,stm32F407ZGT6,初始化,传输数据,Init,ADC,设置,MX
来源: https://www.cnblogs.com/Edwardssss/p/16485125.html