返回列表 发新帖我要提问本帖赏金: 30.00元(功能说明)

[APM32F4] APM32F407 定时器触发ADC+DMA采样测量3ADC采样速度

[复制链接]
 楼主| Alden 发表于 2025-7-22 18:02 | 显示全部楼层 |阅读模式
<
本帖最后由 Alden 于 2025-7-22 18:02 编辑

#技术资源# #申请原创#
上一篇帖子测了APM32F407使用ADC加DMA连续采样3ADC的12个通道,但进一步测试发现这样做虽然能一直用DMA采ADC的数据,但不好确定数据是在什么时刻采的,也不好测量ADC采样的时间,就再调整了下,增加用定时器触发ADC采样。
查看APM32F407的手册可以看到,ADC有多种外部触发的选择,可以根据需要进行选择。
Snipaste_2025-07-22_17-11-57.png
我这里就选择TMR2_TRGO来进行触发。
定时器的配置如下:
  1. void TMR_Init(void) {
  2.         TMR_BaseConfig_T timBaseConfig;
  3.                 RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR2);
  4.         //系统工作主频为168M,由于APB1是4分频,所以tmr2时钟84M计算如下
  5.         timBaseConfig.period = 83;                         //设置定时器时基为125us,(83+1)*(124+1)/(84m) = 125us        
  6.         timBaseConfig.division = 124;                 
  7.         timBaseConfig.clockDivision = TMR_CLOCK_DIV_1;
  8.         timBaseConfig.countMode = TMR_COUNTER_MODE_UP;
  9.         TMR_ConfigTimeBase(TMR2,&timBaseConfig);
  10.         
  11.         //选择外部触发源
  12.         TMR_SelectOutputTrigger(TMR2, TMR_TRGO_SOURCE_UPDATE);
  13.         
  14.         TMR_EnableInterrupt(TMR2,TMR_INT_UPDATE);
  15.         NVIC_EnableIRQRequest(TMR2_IRQn,0,0);
  16.         
  17.         TMR_Enable(TMR2);
  18. }
系统工作主频为168M,由于APB1是4分频,所以tmr2时钟84M计算如下:(83+1)*(124+1)/(84m) = 125us
也就是在默认168M主频下TMR2触发ADC采样的周期是125us.
对应的,ADC的初始化中增加外部触发的配置:
  1. void ADC_Init(void)
  2. {
  3.     GPIO_Config_T gpioConfig;
  4.     ADC_Config_T  adcConfig;
  5.     ADC_CommonConfig_T adcCommonConfig;

  6.     /* RCM Enable*/
  7.     RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA|RCM_AHB1_PERIPH_GPIOB|RCM_AHB1_PERIPH_GPIOC);

  8.     /* GPIO Configuration */
  9.     GPIO_ConfigStructInit(&gpioConfig);
  10.     gpioConfig.pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
  11.     gpioConfig.mode = GPIO_MODE_AN;
  12.     gpioConfig.pupd = GPIO_PUPD_NOPULL;
  13.     GPIO_Config(GPIOA, &gpioConfig);
  14.                
  15.           GPIO_ConfigStructInit(&gpioConfig);
  16.     gpioConfig.pin = GPIO_PIN_0|GPIO_PIN_1;
  17.     gpioConfig.mode = GPIO_MODE_AN;
  18.     gpioConfig.pupd = GPIO_PUPD_NOPULL;
  19.     GPIO_Config(GPIOB, &gpioConfig);
  20.         
  21.           GPIO_ConfigStructInit(&gpioConfig);
  22.     gpioConfig.pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  23.     gpioConfig.mode = GPIO_MODE_AN;
  24.     gpioConfig.pupd = GPIO_PUPD_NOPULL;
  25.     GPIO_Config(GPIOC, &gpioConfig);

  26.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
  27.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC2);
  28.                 RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC3);
  29.     ADC_Reset();

  30.     /* ADC Common Configuration */
  31.     adcCommonConfig.mode        = ADC_MODE_TRIPLE_REGSIMULT;//3ADC规则同步模式
  32.     adcCommonConfig.prescaler   = ADC_PRESCALER_DIV4;
  33.     adcCommonConfig.accessMode  = ADC_ACCESS_MODE_1;
  34.     adcCommonConfig.twoSampling = ADC_TWO_SAMPLING_10CYCLES;
  35.     ADC_CommonConfig(&adcCommonConfig);

  36.     /* ADC Configuration */
  37.     ADC_ConfigStructInit(&adcConfig);

  38.     /* Set resolution*/
  39.     adcConfig.resolution = ADC_RESOLUTION_12BIT;
  40.     /* Set dataAlign*/
  41.     adcConfig.dataAlign = ADC_DATA_ALIGN_RIGHT;
  42.     /* Set scanDir*/
  43.     adcConfig.scanConvMode = ENABLE;
  44.     /* Set convMode continous*/
  45.     adcConfig.continuousConvMode = DISABLE;
  46.     /* Set extTrigEdge*/
  47.     adcConfig.extTrigEdge = ADC_EXT_TRIG_EDGE_RISING;
  48.                 adcConfig.extTrigConv = ADC_EXT_TRIG_CONV_TMR2_TRGO;        //设置ADC使用TMR2触发
  49.     /* Set nbrOfConversion*/
  50.     adcConfig.nbrOfChannel = 4;

  51.     ADC_Config(ADC1, &adcConfig);
  52.     ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_3CYCLES);
  53.     ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_1, 2, ADC_SAMPLETIME_3CYCLES);
  54.                 ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_2, 3, ADC_SAMPLETIME_3CYCLES);
  55.     ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_4, 4, ADC_SAMPLETIME_3CYCLES);

  56.     ADC_Config(ADC2, &adcConfig);
  57.     ADC_ConfigRegularChannel(ADC2, ADC_CHANNEL_5, 1, ADC_SAMPLETIME_3CYCLES);
  58.     ADC_ConfigRegularChannel(ADC2, ADC_CHANNEL_6, 2, ADC_SAMPLETIME_3CYCLES);
  59.                 ADC_ConfigRegularChannel(ADC2, ADC_CHANNEL_8, 3, ADC_SAMPLETIME_3CYCLES);
  60.     ADC_ConfigRegularChannel(ADC2, ADC_CHANNEL_9, 4, ADC_SAMPLETIME_3CYCLES);
  61.                
  62.                 ADC_Config(ADC3, &adcConfig);
  63.     ADC_ConfigRegularChannel(ADC3, ADC_CHANNEL_10, 1, ADC_SAMPLETIME_3CYCLES);
  64.     ADC_ConfigRegularChannel(ADC3, ADC_CHANNEL_11, 2, ADC_SAMPLETIME_3CYCLES);
  65.     ADC_ConfigRegularChannel(ADC3, ADC_CHANNEL_12, 3, ADC_SAMPLETIME_3CYCLES);
  66.     ADC_ConfigRegularChannel(ADC3, ADC_CHANNEL_13, 4, ADC_SAMPLETIME_3CYCLES);
  67.                

  68.                
  69.     ADC_EnableMultiModeDMARequest();
  70.     /* Enable ADC*/
  71.     ADC_Enable(ADC1);
  72.     ADC_Enable(ADC2);
  73.                 ADC_Enable(ADC3);
  74.                 ADC_SoftwareStartConv(ADC1);

  75. }
这样的话ADC就会由定时器TMR2触发采样,采样完成后有DMA搬运到数组中,触发DMA完成中断进行数据处理。
  1. void DMA2_STR0_IRQHandler(void)
  2. {
  3.         if(DMA_ReadIntFlag(DMA2_Stream0,DMA_INT_TCI**0) != RESET)
  4.         {
  5.                                 APM_MINI_LEDToggle(LED2);
  6.                                         APM_MINI_LEDOn(LED2);
  7.                                         ADC1_CH0_ConvertedValue = (float)DMA_DualConvertedValue[0]/4095*3.3f;
  8.                                         ADC2_CH5_ConvertedValue = (float)DMA_DualConvertedValue[1]/4095*3.3f;
  9.                                         ADC3_CH10_ConvertedValue = (float)DMA_DualConvertedValue[2]/4095*3.3f;
  10.                                        
  11.                                         ADC1_CH1_ConvertedValue = (float)DMA_DualConvertedValue[3]/4095*3.3f;
  12.                                         ADC2_CH6_ConvertedValue = (float)DMA_DualConvertedValue[4]/4095*3.3f;
  13.                                         ADC3_CH11_ConvertedValue = (float)DMA_DualConvertedValue[5]/4095*3.3f;
  14.                                        
  15.                                         ADC1_CH2_ConvertedValue = (float)DMA_DualConvertedValue[6]/4095*3.3f;
  16.                                         ADC2_CH8_ConvertedValue = (float)DMA_DualConvertedValue[7]/4095*3.3f;
  17.                                         ADC3_CH12_ConvertedValue = (float)DMA_DualConvertedValue[8]/4095*3.3f;
  18.                                        
  19.                                         ADC1_CH4_ConvertedValue = (float)DMA_DualConvertedValue[9]/4095*3.3f;
  20.                                         ADC2_CH9_ConvertedValue = (float)DMA_DualConvertedValue[10]/4095*3.3f;
  21.                                         ADC3_CH13_ConvertedValue = (float)DMA_DualConvertedValue[11]/4095*3.3f;
  22.         DMA_ClearIntFlag(DMA2_Stream0,DMA_INT_TCI**0);
  23.         }
  24. }

  25. void TMR2_IRQHandler(void){
  26.         if (TMR_ReadIntFlag(TMR2, TMR_INT_UPDATE) != RESET) {
  27.                                 APM_MINI_LEDOff(LED2);
  28.                 TMR_ClearIntFlag(TMR2, TMR_INT_UPDATE);
  29.                 }
  30. }
同时,这样也可以使用一个IO在TMR2中断中置高,在DMA完成中断中置低,IO的高电平时间就相当于ADC采样转化的时间。
我们也可以先看看理论上的ADC采样时间改如何计算:
ADC时钟在APB2总线上,最大是主频的二分频也就是84Mhz。
ADC的时钟通过    adcCommonConfig.prescaler   = ADC_PRESCALER_DIV4;再分频下来。
这里测试是4分频也就是21Mhz
ADC的转换时间公司在用户手册中可以看到:
TCONV=采样时间+12 个周期;采样时间由 SMPCYCCFGx[2:0]位控制,最小采样周期为 3 个
也就是我配置的:    ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_3CYCLES);
所以我目前配置的采样频率是21M÷(3+12)=1.4M,对应的采样时间为0.714us。
我使用三ADC采12个通道需要采4次也就是我目前配置的理论采样时间就是4*0.713us=2.856us。
而实际的采样时间我们通过示波器输出来看:
DSTSS3.png
实际采样时间是3.333us

将采样周期改成15后:   ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_15CYCLES);
理论采样时间就是5.143us
实际采样时间是5.529us
DSTSS4.png
可以看到实际值比理论值略大零点几us,这主要是DMA传输以及进出中断的指令占的时间.
所以APM32F407ADC的采样时间与理论是相符的。

打赏榜单

21小跑堂 打赏了 30.00 元 2025-07-28
理由:恭喜通过原创审核!期待您更多的原创作品~~

评论

书接上文,增加定时器触发ADC采样,通过定时器的辅助,使多个ADC多通通加DMA采样更为可控,效果更佳。  发表于 2025-7-28 17:48
[url=home.php?mod=space&uid=760190]@21小跑堂[/url]  发表于 2025-7-22 18:03
绝影孤狼 发表于 2025-7-29 20:53 | 显示全部楼层
非常详细的配置过程,学习了!不过我有个疑问,DMA搬运数据时的延迟对采样时间的影响大吗?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

113

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部