[STM32F4] STM32F407三重ADC交替采样实现方案

[复制链接]
37|11
荣陶陶 发表于 2026-3-13 17:05 | 显示全部楼层 |阅读模式
一、硬件配置
电路连接
通道分配:三个ADC共用同一输入通道(如ADC1_IN5、ADC2_IN5、ADC3_IN5)

电源与滤波:

ADC输入端并联10kΩ电阻 + 100nF电容(低通滤波)

电源引脚添加0.1μF陶瓷电容并联10μF电解电容

关键参数
最大采样率:三重交替模式下理论可达7.2MSPS(实际约6MSPS)

时钟配置:APB2时钟≥144MHz(分频后ADC时钟≤36MHz)

触发源:推荐使用定时器(如TIM8)触发,确保严格同步

二、软件配置(CubeMX)
1. 时钟树配置
HSE → PLL → 系统时钟(168MHz)
APB2分频系数:2 → 84MHz(满足ADC时钟≤36MHz)


2. ADC模式设置
主从模式:选择Triple interleaved mode only(三重交替模式)

触发源:选择定时器触发(如TIM8的更新事件)

DMA模式:DMA access mode 1(三重交替专用模式)

3. 定时器配置
时钟源:内部时钟(84MHz)

预分频系数:1

重装载值:14 → 触发频率=84MHz/(1+1)/(14+1)=3MHz

触发事件:更新事件(Update Event)

三、代码实现
1. 初始化代码(HAL库)
// main.c
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

void MX_ADC1_Init(void) {
  ADC_ChannelConfTypeDef sConfig = {0};

  // 三重交替模式配置
  ADC_CommonInitTypeDef ADC_CommonInitStructure = {0};
  ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult;  // 三重同步规则模式
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;  // 84MHz/4=21MHz
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;  // DMA模式1
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;  // 采样延迟
  HAL_ADCEx_CommonInit(&hadc1, &ADC_CommonInitStructure);

  // 通道配置
  sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = 1;
  HAL_ADC_ConfigChannelAttenuation(&hadc1, ADC_CHANNEL_5, ADC_ATTENUATION_11DB);
}

void MX_DMA_Init(void) {
  __HAL_RCC_DMA2_CLK_ENABLE();
  hdma_adc1.Instance = DMA2_Stream0;
  hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
  hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
  hdma_adc1.Init.Mode = DMA_CIRCULAR;  // 循环模式
  HAL_DMA_Init(&hdma_adc1);
  __HAL_LINKDMA(&hadc1, hdmarx, hdma_adc1);
}


2. 中断回调函数
// 三重ADC数据拆分(DMA传输32位数据)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
  uint32_t raw_data = hdma_adc1.Instance->CNDTR;  // 当前剩余数据量
  for (int i=0; i<ADC_DMA_SIZE; i++) {
    uint32_t temp = ((uint32_t)adc_dma_buffer[i*2] << 16) | adc_dma_buffer[i*2+1];
    adc_buffer = (float)(temp & 0x0FFF) * 3.3f / 4095.0f;  // 转换为电压值
  }
}


参考代码 STM32F407自带ADC模块的三重采样 www.youwenfan.com/contentcsr/102138.html

四、关键问题与解决方案



————————————————
版权声明:本文为CSDN博主「chao189844」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chao189844/article/details/158739293

公羊子丹 发表于 2026-3-14 08:18 | 显示全部楼层
楼主这套F407三重ADC交替采样的方案太实用了,我想问下实际调试时,三个ADC的采样延迟除了设5个周期,有没有根据采样率调整的小技巧?比如高采样率下该怎么选延迟值。
周半梅 发表于 2026-3-14 08:19 | 显示全部楼层
我之前做F4的多ADC采样时,遇到过数据错位的问题,最后发现是DMA传输宽度没配对,建议你检查下DMA配置里的PeriphDataAlignment,三重ADC得设成32位才不会错。
帛灿灿 发表于 2026-3-14 08:20 | 显示全部楼层
感谢楼主把CubeMX配置和代码都写得这么细,想问下用TIM8触发采样时,有没有做触发同步的校准?比如定时器更新事件和ADC采样时钟的相位对齐,会不会影响采样精度?
童雨竹 发表于 2026-3-14 08:21 | 显示全部楼层
分享个小经验,F407的ADC引脚采样前一定要做阻抗匹配,尤其是三重交替采样时,输入阻抗太高会导致采样值不准,建议在引脚处加个几十欧的匹配电阻,亲测有效。
万图 发表于 2026-3-14 08:22 | 显示全部楼层
想问下楼主,你的adc_dma_buffer数组是怎么定义的?三重ADC交替采样的DMA数据是按ADC1、ADC2、ADC3顺序存储的吗?数据拆分这块新手很容易搞混,求细节。
Wordsworth 发表于 2026-3-14 08:23 | 显示全部楼层
我建议你在ADC初始化里加上校准函数,HAL_ADCEx_Calibration_Start(&hadc1),F4的ADC上电后不校准的话,采样误差会变大,尤其是多通道交替采样时,校准很有必要。
Bblythe 发表于 2026-3-14 08:24 | 显示全部楼层
看楼主把ADC时钟分频设为4,得到21MHz,想问下如果想提升采样率,把分频改2到42MHz行不行?会不会超过芯片手册的限值,或者导致采样精度大幅下降?
Pulitzer 发表于 2026-3-14 08:25 | 显示全部楼层
这方案里用了DMA循环模式,我提醒下各位,循环模式下一定要注意数据缓冲区的大小,别出现缓冲区溢出的情况,最好在回调函数里做个数据标志位,防止数据覆盖。
Uriah 发表于 2026-3-14 08:26 | 显示全部楼层
楼主的回调函数里只处理了ADC的原始数据,想问下有没有做过滤波处理?三重ADC采样的高频噪声还挺明显的,用简单的滑动平均滤波的话,取多少个点比较合适?
Clyde011 发表于 2026-3-14 08:27 | 显示全部楼层
我之前做三重ADC采样时,遇到过定时器触发不生效的问题,检查了半天发现是ADC的触发极性设错了,建议大家配置时确认下TIM8的TRGO触发极性和ADC的触发检测极性一致。
香水城 发表于 2026-3-15 08:32 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

170

主题

594

帖子

1

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