|
我这里基于STM32H563的开发板和STM32HAL库,以及STM32CubeMx配置工具,演示一下ADC+TIM+DMA的实现过程。具体实现是这样的: 有8个ADC通道工作在单次扫码模式,由TIM3的更新事件触发启动之,ADC的结果由DMA搬运到指定内存,同时还要测量每次8个ADC通道转换完成所用的时间。
如上图所示,TIM3工作在向上计数模式,图中红色箭头表示TIM3发生更新事件的时间点,蓝色箭头表示每8个通道转换完成的时间点。下面实现过程中用DMA完成事件替代8通道转换完成事件。根据目前设计,我们只要在DMA完成中断里读取触发定时器的计数器的值即可得到每轮8个通道转换所用的时间。 下面开始使用STM32CubeMx进行各种初始配置。系统主频配置在200Mhz,TIMER使用200Mhz系统时钟作为时钟源【主频其实可以配置到250MHz】。
现在对TIM3进行配置,选择其更新事件作为TRGO信号,用来触发启动ADC。
根据上面时基参数的配置,TIM3的计数频率为1Mhz,即每一个计数脉冲对应1us,计数溢出周期为20ms。TIM3将按此周期定时触发启动ADC。 下面是ADC的基本配置,具体用到ADC1的8个通道的规则转换。
为了便于测试和计算,我这里将8个通道的ADC参数除了RANk顺序外,其它都配置得一样,并启用DMA循环传输功能。
下面是有关DMA的配置,使用DMA标准请求模式,外设到内存的传输方向,工作在循环模式。
完成配置后创建工程,添加用户代码。 这里定义了两个32位变量,分别用于存放ADC转换结果和记录每轮ADC转换所用时间,单位是us。 / USER CODE END 2 / uint32_t ADC_Result[8]; //存放ADC转换结果 volatile uint32_t ElapsedByADC[8];//记录每轮ADC转换所用时间 / USER CODE BEGIN 2 / HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED); __HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_UPDATE); __HAL_ADC_CLEAR_FLAG(&hadc1, ADC_FLAG_EOC); HAL_ADC_Start_DMA(&hadc1, (uint32_t *)ADC_Result, 8); HAL_TIM_Base_Start(&htim3); 在DMA传输完成中断回调函数里记录每一轮ADC转换所用时间: void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { static uint8_t i=0; if (i==8) i= 0; ElapsedByADC[i]= TIM3->CNT ((TIM3->PSC +1)/200); / us unit */ i++; } 下面是测试结果的截图【因最后两个ADC通道是测试的两个内部信号,其结果比较稳定,其它ADC输入管脚都是浮空状态】:
从当前测试结果来看,每8个ADC通道转换完成所用时间为100us,结果也稳定。 我们不妨根据ADC目前参数,计算下它该花多少时间。现在每个通道的采样时间都是247.5个ADC clock,加上转换时间12.5个clock,那么每个通道单次总转换时间为260个ADC clock。现在ADC的转换时钟为200MHz的10分频,即20MHz。算下来8个通道的总转换时间应该是104us的样子。
现在是理论计算结果比实测要大些,有点偏差,但误差不大。这个误差会不会跟我所用TIMER的计数精度有关呢?前面的TIM3的计数频率为1MHz,如果我把计数频率提升到10MHz,其它参数不动,看看结果会怎么样?【这样调整后TIM3的溢出周期变短了,但依然远长于ADC一轮转换所需要的时间】 我们再来看看调整TIM3计数频率后的的结果:
不难看出,此次的测试结果跟刚才的理论计算值就非常接近了,实测值比计算值稍微大一点也是合理的,毕竟基于DMA传输完成中断服务代码获取时间的动作要比ADC实际转换完成晚些。 一般来讲,ADC的转换时间是不需要专门来测量的。除非个别调试场合的确需要确认验证外,其它时候或许是出于好奇想测测。其实,这种测试方法也不总是靠谱,在上面实验过程中我们注意到统计时间的计时分辨率就对结果就有影响。如果不是被测时间较长的话,就不要使用系统滴答个数来统计。在STM32工程里,通常系统的滴答计时分辨率为1ms。 再比方,如果系统中DMA请求及响应很多而频繁,用于搬运ADC结果的DMA通道优先级又偏低,或者说系统中的中断频繁,而DMA传输完成中断的优先级又偏低,这都会影响测试结果,影响程度视情况而定。 刚好最近跟其他人谈及相关话题,就此顺便做个分享以供参考。 文章出处:茶话MCU [/i] |
经验分享 | STM32N6 ADC DMA 传输失败案例分享
实战经验 | MC SDK V6.x软件HSO功能ADC采样设计说明
经验分享 | 为什么重启ADC的DMA传输要先停掉ADC?
经验分享 | 为什么重启ADC的DMA传输要先停掉ADC?
经验分享 | STM32 ADC过采样话题
经验分享 | STM32双定时器+ADC+DMA实战案例
经验分享 | STM32U5系列TIMER+DMA+DAC应用演示
经验分享 | 基于STM32片内信号的ADC应用演示
经验分享 | STM32F0 ADC结果挪位的问题分析及解决
经验分享 | 三个 ADC 同步模式配置以及 CubeMx 错误配置的解决方法
微信公众号
手机版