你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F407 ADC Dual regular simultaneous only 模式下最高采样率仅 96 kHz,960 kHz 无法工作,求助!

[复制链接]
BOEING777ER 提问时间:2025-5-4 11:56 / 未解决

一、平台及配置

  • MCU 型号 :STM32F407VG (Cortex‑M4)
  • ADC :ADC1 + ADC2,Dual regular simultaneous only 模式
  • 触发源 :TIM2 TRGO 外部触发
  • ADC 时钟 :PCLK2=96 MHz,ADC prescaler=DIV2 → f<sub>ADC</sub>=48 MHz
  • 采样时间 :15 ADC 时钟周期(最小)
  • 分辨率 :12 位
  • DMA :双通道交替存储 Regular 转换结果

二、理论计算

  • ADC 时钟

    fADC=PCLK2prescaler=96 MHz2=48 MHzf_{\rm ADC} = \dfrac{\rm PCLK2}{\rm prescaler} = \dfrac{96\,\text{MHz}}{2} = 48\,\text{MHz}f**ADC****=prescalerPCLK2****=296MHz****=48MHz**

  • 转换周期

    最短采样时间设为 15 ADC 周期,加上 12.5 周期的转换时间,总共

    Tconv=15+12.548 MHz≈0.571 μs T_{\rm conv} = \frac{15 + 12.5}{48\,\text{MHz}} \approx 0.571\ \mu\text{s}T**conv****=48MHz15+12.5****0.571 μs**

  • 理论最高采样率

    fsamp=1Tconv≈10.571 μs≈1.745 MSPS(每通道) f{\rm samp} = \frac{1}{T{\rm conv}} \approx \frac{1}{0.571\,\mu\text{s}} \approx 1.745\ \text{MSPS(每通道)}f**samp****=Tconv****1****0.571μs1****1.745 MSPS(每通道)**

Dual regular simultaneous only 模式下,ADC1+ADC2 同步启动,虽然同时采样,但各自的吞吐量仍与单 ADC 相同,即每路 ≈1.745 MSPS。


三、实测现象

  • 触发频率 ≤ 96 kHz

    使用 TIM2 TRGO≤96 kHz 时,ADC1+ADC2 在 Dual regular simultaneous only 模式下可稳定响应,每路采样率≈96 kHz,DMA 半/全传输中断按期望触发,数据正常。

  • 触发频率 = 960 kHz

    尽管示波器确认 TIM2 TRGO 输出仍为 960 kHz,ADC 接收不到触发信号,DMA 不产生中断,中断回调不再执行,采样彻底失效。


备注 :实测最高只能到 ≈96 kHz,而非理论的 ≈1.7 MSPS。可能原因包括:采样时间配置未真正生效(仍在用 480 周期)、HAL/DMA 调用了额外开销、ADC 启动同步仲裁逻辑等。

四、已排查项

  1. CubeMX/HAL 配置确认:Dual regular simultaneous only、采样时间 15、ADC prescaler DIV2;
  2. TIM2 已配置 Master Mode = Update → TRGO,每周期触发一次 ADC;
  3. DMA 流/通道、FIFO、半/全中断配置正确,无死锁或缓存溢出;
  4. 关掉其他外设、提高 DMA 优先级,均无改善;
  5. 软件触发模式下,理论速率下限仍远低于 960 kHz。

五、求助方向

  1. Dual regular simultaneous only 模式 在硬件层面是否有隐藏的同步或仲裁开销?

  2. 除了采样时间和 f<sub>ADC</sub>,是否还有其他寄存器设置(如 ADC_CCR、中断/模拟看门狗)影响高速触发响应?

  3. TIMx TRGO 在高触发频率下是否存在精度或同步瓶颈?

  4. 若要接近 1 MSPS 级别,有哪些最佳实践或寄存器必须开启/关闭?

  5. 有没有前辈实测能在该模式下超 96 kHz 的经验?

  6. void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
    {
        if(hadc->Instance == ADC1)  // 以 ADC1 作为主 ADC(多模式中 ADC1 和 ADC2 同步)
        {
            // print_log("half\n");
            // //打印GetTick
            // print_log("GetTick: %d\n", HAL_GetTick());
            // 处理 adcBuffer 前半部分的数据:下标 0 到 ADC_BUFFER_SIZE/2 - 1
            processADCData(&adcBuffer[0], ADC_BUFFER_SIZE/2);
        }
    }
    
    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
    {
        if(hadc->Instance == ADC1)
        {
            // print_log("full\n");
            // //打印GetTick
            // print_log("GetTick: %d\n", HAL_GetTick());
            // 处理 adcBuffer 后半部分的数据:下标 ADC_BUFFER_SIZE/2 到 ADC_BUFFER_SIZE - 1
            processADCData(&adcBuffer[ADC_BUFFER_SIZE/2], ADC_BUFFER_SIZE/2);
        }
    }
    
    void processADCData(uint32_t *buffer, uint32_t length)
    {
        // 例如每 40 个数据为一组(根据你的配置,每个通道40个样本)
        uint32_t groupSize = 4;  
        uint32_t numGroups = length / groupSize;
    
        for(uint32_t i = 0; i < numGroups; i++)
        {
            uint32_t startIndex = i * groupSize;
            // 假设每组中丢弃前1个,处理后3个有效样本
            uint32_t validSamples = 3;
            int32_t sumDiff = 0;
    
            for(uint32_t j = 1; j < 1 + validSamples; j++)
            {
                // 对于多模式 ADC,低16位是 ADC1 的数据,高16位是 ADC2 的数据
                uint16_t adc1_value = buffer[startIndex + j] & 0xFFFF;
                uint16_t adc2_value = (buffer[startIndex + j] >> 16) & 0xFFFF;
                int16_t diff = (int16_t)adc1_value - (int16_t)adc2_value;
                sumDiff += diff;
                // if(j == 39 && i < 3)
                // {
                //     print_log("ADC1: %d, ADC2: %d, Diff: %d\n", adc1_value, adc2_value, diff);
                // }
            }
            // 此处 sumDiff 为该组采集数据的累加结果,可根据需要存储或后续处理
            //processChannelResult(i, sumDiff);
            //发送给BUF_NUM_S0+i
            float sumDiff_f = (float)sumDiff;
         if(i < 16)
               sendDatatoBuf(BUF_NUM_S0+ i , (uint8_t*)&sumDiff_f, sizeof(sumDiff_f));
            // 例如打印结果
    //       if(i < 3)
             // print_log("Group %d: ADC1-ADC2 SumDiff = %d\n", i, sumDiff);
        }
    }
7.
8.
9.
收藏 评论2 发布时间:2025-5-4 11:56

举报

2个回答
dx88 回答时间:3 天前

👍

xmshao 回答时间:昨天 10:24
1、你这里说的96KHz不是采样率,而应该触发频率。


2、触发频率除了遵守手册中约定的最大值外,在具体应用中要跟ADC模块中最长转换序列及转换时间决定,在多模块同时采样模式中,触发间隔要比任一模块中所需最长的转换时间要长些,至少不能短。


3、你好像在说给ADC模块的时钟48MHz,其实,这里的ADC模块能接受的最高时钟是36MHz.


4、假设你现在的采样时间是15个ADC clock,加上转换时间12个Clock,那么总转换时间就是27个ADC clock. 假设ADC时钟是36MHz,那么触发频率就不能高于36/27Mhz,即不能高于1.33MHz.


5、我以上面第4项的条件基于dual ADC simultaneous模式进行验证,ADC1 ADC2各取1个通道,分别接GND和VDD. 使用公共数据寄存器通过DMA搬运。实测下来当触发频率高于1.4MHz时的确出现问题,即触发频率跟数据转换的频率不同步了。


使用TIMER进行触发,本意是每次触发20次做20对数据的转换,看看下面4不同触发频率下的情形。注:每个32位数据包含两个通道的结果。
rrr.png rrr1.png


从上面测试结果来看,结果跟预期分析一致。


6、你现在触发频率上不去,请确认下采样时间到底是多少?ADC模块的时钟到底是多少?


7、结合上面分析与测试,当触发频率高于转换速率时,会出现触发事件被丢失的情况,这个情形结合DMA normal模式,可能没法出现DMA完成
事件及相关中断的问题。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版