1. 项目背景和需求
最近在做一个电源采集板,用 STM32H743 做三路 10kHz 电流采集和三路差分电压采集。电流这边要求采样时刻尽量固定,电压采集对频率没有那么苛刻。为了把 CPU 从采样流程里解放出来,我最后选了定时器触发 ADC,再用 DMA 把数据搬走。CPU 只在一帧数据准备好后再处理,这样系统会轻松很多。
这种场景不适合让 CPU 亲自盯着每一次采样。频率一上去,调度和中断开销很容易把事情搞复杂,数据稳定性也会受影响。定时器负责节拍,ADC 负责采样,DMA 负责搬运,三者分工清楚,实际调起来反而更顺手。
STM32H743 的 ADC 和 DMA 能力都不弱,但配置细节不少,尤其是时钟、触发源和通道顺序。前面没理顺,后面排查起来会很磨人。
2. 硬件平台和开发环境
这次用的是 STM32H743ZI,主频 480MHz,内置 3 个 16 位 ADC。开发环境是 STM32CubeMX 6.15.0、H7 HAL 库 1.12.1,编译器用 Keil MDK。
我选这个组合主要是图稳。新版本不一定不好,但在这种外设配置比较密集的项目里,工具链一变,很多边缘问题会跟着冒出来。先把版本固定住,后面排错省心不少。
硬件连接上,三路电流信号接到 ADC1 的 IN3、IN10 和 IN15,走单端输入;差分电压则分别用 ADC2 和 ADC3 的差分输入通道。这里没有搞太花的方案,先把采样链路跑通更重要。
ADC 时钟这块要卡住上限。STM32H743 的 ADC 时钟最高不能超过 36MHz,我这里把系统时钟配置后再经过 2 分频,最后得到 32MHz,性能和稳定性都比较平衡。时钟超标的话,轻则数据不稳,重则 ADC 直接异常,这个坑不值得踩。
3. CubeMX 里的关键配置
3.1 ADC 配置
在 CubeMX 里先配 ADC1。Parameter Settings 里有几个参数是绕不开的,采样顺序、触发源、分辨率、采样时间,都得和前面的采集目标对上。尤其是定时器触发这一项,选错了后面看波形会很难受,表面上能跑,采样点其实已经偏了。
ADC1 这边负责三路电流采样,通道顺序要固定下来。DMA 读出来的数据是按顺序排的,后面做解析时就按这个顺序取,不要中途再改通道排列,不然容易把数据对应关系弄乱。
差分电压通道由 ADC2 和 ADC3 处理,配置时要确保输入模式和硬件接法一致。差分输入和单端输入不是一回事,这里如果按单端思路去配,读数会直接不对。
3.2 定时器触发
定时器这部分的作用很简单:给 ADC 提供稳定的采样节拍。10kHz 的电流采样,定时器频率和分频参数要算准,别只看理论值,最后还得和实际时钟树对一遍。
我这里用定时器输出 TRGO 作为 ADC 外部触发源。这样 ADC 不是自己随便起跑,而是跟着定时器的节拍走,采样时间点会更统一。这个方案在波形不那么'完美'的现场环境里,优势很明显。
3.3 DMA 配置
DMA 主要做两件事:把 ADC 数据搬到内存,尽量少打断 CPU。对于多通道采样,建议直接用循环模式,配合缓冲区连续接收。这样采样和处理可以错开,不用每次都手工重启 DMA。
这里最容易出问题的是缓冲区大小和通道数不匹配。DMA 开起来不代表数据就对了,数组长度、通道数量、采样顺序必须一起看,否则后面拿到的数组会乱成一团。
4. 实际调试时碰到的几个点
最开始我遇到的第一个问题是 ADC 时钟配置不够严谨,表面上能初始化,实际采样值却不稳定。把时钟重新按 32MHz 收回来以后,问题就明显少了。
第二个问题出在通道顺序和 DMA 数据解析上。ADC 配置改过一次后,代码里的数据索引没同步更新,结果电流和电压数据被错位读了。这个问题不复杂,但很容易浪费时间,因为串口打印出来的值看着都'像那么回事'。
第三个问题是触发源选择。定时器触发和软件触发混着试的时候,采样节拍会变得不连续,最终表现就是波形上偶尔有抖动。后面把触发方式统一成定时器后,数据就规整多了。
5. 小结
这套方案的核心不是'把 ADC 跑起来',而是把采样、搬运和处理拆开。定时器负责节拍,ADC 负责采样,DMA 负责传输,CPU 只做最后的业务处理。对高频采集来说,这种结构更稳,也更省资源。
STM32H743 的外设能力足够用,真正费时间的还是配置细节。时钟别超,触发源别配错,DMA 缓冲区别和通道顺序打架,基本就能少掉一大半调试时间。

