ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STM32G474 HRTIM触发ADC采样:PWM中间时刻精准采集,消除开关噪声

STM32G474 HRTIM触发ADC采样:PWM中间时刻精准采集,消除开关噪声 简介这套基于 STM32CubeIDE 的完整工程面向 STM32G474 微控制器开发者解决高开关频率下 PWM 噪声干扰采样精度的问题。工程演示如何利用 HRTIM 的多个触发事件精确控制多路 ADC 在不同时刻启动转换再借助 DMA 完成数据传输无需 CPU 干预同时通过串口将采样结果打印出来便于实时观测。核心技巧是将 ADC 采样点对准 PWM 波形的中间时刻避开开关管通断瞬间的电压电流尖峰从而获得更稳定的采样值适合数字电源、电机控制、电池管理等对采样时序要求较高的应用场景。压缩包共 281 个文件约 15.64MB包含 CubeMX 的 .ioc 配置、C/H 源码、链接脚本以及编译生成的 o/elf 等文件目录结构清晰导入后即可编译验证。该资源已有 1199 人学习下载尤其适合具有一定 STM32 基础、希望深入理解 HRTIM 与 ADC 同步机制的工程师进阶参考。通过这个工程读者能够掌握多通道 ADC 的触发源配置、DMA 缓冲区管理以及 PWM 中间时刻采样的实现思路为后续开发高性能数字电源或电机控制器打下扎实基础。 做电机控制、数字电源的朋友十有八九都被开关噪声折磨过。PWM一翻转ADC采回来的波形上全是毛刺电流环根本没法调。这个项目围绕STM32G474展开核心思路是用HRTIM在PWM中间时刻触发ADC采样让多路采样数据通过DMA自动搬运最后由串口打印出来用最少的CPU开销拿到最干净的波形。一句话概括就是在噪声最小的那个时间窗口把数据稳稳抓出来。这套方案在FOC电机控制、LLC电源、PFC这类高频开关场景里特别实用适合已经在用STM32做控制、但对HRTIM还不算熟或者不知道采样点该怎么卡的工程师和进阶玩家。我会从方案选型、外设配置、代码实现到问题排查都讲透最后还会分享几个只有实际调过才会懂的坑。1. 方案整体思路为什么是“PWM中间时刻采样”1.1 开关噪声到底有多害人功率电路里的噪声不是玄学而是物理规律。MOSFET或IGBT在开通和关断的瞬间电压和电流变化率极高dv/dt可以到几十甚至上百V/usdi/dt同样惊人。这个瞬间会在母线上激发出强烈的振铃同时通过寄生电容耦合到ADC采样回路上导致采样值瞬间偏出真实值几个甚至几十个LSB。这种开关噪声的最大特点就是窄而尖持续时间通常在几十纳秒到几百纳秒但幅度非常大。如果ADC恰好在这个窗口里采样结果会非常离谱。我之前调一个半桥电路时同一路电流信号在PWM边沿附近采样数值跳动了将近30%而把采样点往后挪几百纳秒数据立刻就稳定了。这就是为什么大家都在说采样时序要对而不是换一个更贵的运放就能解决。中心对齐PWM下每半个周期中间会有一段平稳区域此时所有开关管已经完成切换母线电压和电流处于相对稳定的状态。把这个点作为ADC采样时刻理论上可以最大程度避开开关噪声。这个思路广泛用于FOC电流采样、LLC谐振电流检测等场景也是本项目的核心设计目标。1.2 为什么这条链路是HRTIM ADC DMA先解释一个很多人会问的问题普通定时器不能做吗STM32G474的TIM1/TIM8确实也能输出PWM并触发ADC但HRTIM在处理这类高精度触发任务时有明显优势。HRTIM内部包含多个定时器单元每个单元都有独立比较寄存器可以生成多个不同相位、不同占空比的PWM信号同时还能把任意单元的特定事件映射到ADC触发信号上。更重要的是HRTIM触发ADC是完全由硬件完成的不经过中断没有软件延迟抖动。至于DMA则是在解决另一个问题。多路ADC采样意味着每次PWM周期都会产生好几个转换结果如果用串口直接打印CPU会持续被占用如果进中断搬运数据中断延迟又会反过来干扰其他实时控制任务。而DMA可以在ADC转换完成后直接把结果搬到内存缓冲区整个过程不劳烦CPU采样频率再高也不怕。这三者组合起来实际上就是一条硬件数据流水线HRTIM负责告诉ADC“现在可以采了”ADC按顺序把多路信号转换完DMA把结果搬走CPU只在需要时把数据整理成串口帧发出去。整个链路中间没有软件干预点所以采样时刻非常稳定可以做到每个PWM周期都在同一时间点采样。2. 关键外设配置把HRTIM、ADC、DMA串成一条流水线2.1 HRTIM怎么配置出PWM并产生ADC触发先用一个具体参数来聊假设PWM频率20kHz中心对齐模式HRTIM时钟是170MHz。这个模式下计数器从0递增到周期寄存器PER再从PER递减到0完整的PWM周期对应两倍PER计数时间。频率公式是fPWM fHRTIM / (2 * PER)。反推下来PER应该设为4250也就是170000000 / 20000 / 2。计数到达PER的时刻正好是PWM周期的正中间。把这个事件映射到HRTIM的ADC触发引脚ADC就会在这个时间点被硬件自动触发。CubeMX里要在HRTIM配置页选择TIMA单元或者其他单元配置为Center-Aligned模式把周期设为4250CMP寄存器按目标占空比设置。ADC触发需要单独配置在HRTIM的ADC Trigger选项中把ADC Trigger 1绑定到Timer A的Period事件上。这里的核心难点在于理解“哪一个事件对应PWM中间”。中心对齐模式下计数到上限即PER值时是PWM周期中点的上半部分计数到0时是中点的下半部分。补设定为在PER事件触发其实就是在高电平区间的中点采样。如果你要测的是下管导通时的电流就需要配置在计数器归零的窗口附近触发这时候可以用另一个事件或调整占空比窗口来对齐别死套一个配置得根据主电路的拓扑来选。2.2 ADC多路采样与DMA搬运配置STM32G474的内部ADC资源非常充足所以多路采样通常有两种做法。一种是单个ADC实例扫描多个通道适合通道数不多、对同步性要求不高的场景另一种是多个ADC实例同时触发每个ADC采样一路信号适合需要真正同步采集三相电流的场景。如果只是采样三四路信号用单个ADC加扫描模式就够。CubeMX里要打开ADC1把需要的通道全部加入开启Scan Conversion Mode转换顺序按你的目标来排。触发源选择HRTIM ADC Trigger 1这一步一定要选对外部触发否则HRTIM的事件根本进不来。采样时间的设置也要留意。中间时刻采样虽然躲开了开关噪声但采样窗口本身是有限的。如果设置过长的采样时间ADC转换还没结束PWM已经进入下一个边沿结果还是会被干扰。建议12位分辨率下采样时间选2.5周期或3.5周期总转换时间大约250ns到350ns对20kHz级别的应用来说完全够用。DMA配置的关键点有两个。第一外设地址固定为ADC1的数据寄存器内存地址指向你的数组第二数据宽度必须与ADC的数据寄存器对齐。这里有个常见的坑很多人直接把数据宽度搞成Byte搬运结果全是错的应该根据你生成的ADC数据类型选Half Word或Word。STM32G474的DMA有DMAMUX可以把ADC请求灵活映射到任意DMA通道基本不用发愁资源冲突。2.3 串口打印那一路怎么处理数据采回来是要给人看的。如果直接用HAL_UART_Transmit阻塞发送在20kHz采样率下CPU会被拖死因为每次要发送的数据还没传完下一轮采样已经开始了。所以我建议串口也走DMA发送。做法也很简单维护一个采样数据缓冲区在主循环里把当前DMA缓冲区里的数据处理成可读格式再通过串口DMA发出去。发送期间CPU不阻塞可以继续处理其他任务。数据格式上第一版图省事可以直接以十六进制或原始值方式发送用串口助手查看。但如果你想把数据导入Excel或者画图工具对比波形最好加上帧头帧尾和校验。比如帧头用0xAA 0x55接着是数据长度、各路ADC值、校验和。这样在电脑端解析起来非常方便。3. 实操过程从CubeMX到代码跑通3.1 CubeMX里的关键配置点先搭工程骨架。时钟树里把系统时钟配置到170MHz确保HRTIM也是170MHz这是整个高精度定时的基础。如果时钟配低了HRTIM的时序精度会直接打折。HRTIM配置页面按下面几步操作Timer A配置为Center-Aligned mode周期寄存器PER为4250。CMP1寄存器设置你需要的占空比如果要默认50%就设为2125。在ADC Trigger配置里把ADC Trigger 1的来源选择为Timer A的Period事件。输出通道开启并配置好极性。ADC配置页面ADC1开启Scan Mode加入你要采样的所有通道。触发源选择HRTIM ADC Trigger 1。连续转换模式可以不勾我们只需要每次触发转换一轮。DMA请求务必打开模式选Circular数据宽度按ADC寄存器宽度选择。USART配置页面选一个串口波特率115200或460800均可。注意采样率如果很高115200波特率可能来不及发完所有数据就得考虑降采样率或提升波特率。开启USART的DMA发送请求也可以顺带开个接收方便以后做上位机交互。这些都配置好之后生成工程。要注意CubeMX生成的HRTIM初始化和ADC初始化代码基本是完整的但HRTIM的ADC触发启动函数需要手动添加调用。3.2 核心代码启动链路与数据处理工程生成后要把整条数据链跑起来。代码层面的关键点如下// 启动HRTIM的PWM输出这里以Timer A为例 HAL_HRTIM_PWMStart(hhrtim, HRTIM_TIMERID_TIMER_A); // 启动HRTIM的ADC触发信号 HAL_HRTIM_ADCTrigStart(hhrtim, HRTIM_TRIGGER_ADC1); // 启动ADC的DMA传输目标缓冲区是adc_buf HAL_ADC_Start_DMA(hadc1, (uint32_t *)adc_buf, ADC_CHANNEL_COUNT);注意调用顺序。先把HRTIM触发源打开再启动ADC的DMA传输这样触发事件到来时ADC才会响应。顺序反了或者漏掉HAL_HRTIM_ADCTrigStart大概率会出现没有采样数据的现象。主循环里的处理逻辑比较简洁while (1) { // 检查DMA传输完成标志由ADC DMA中断置位 if (adc_dma_done) { // 关闭中断防止数据被覆盖 __disable_irq(); memcpy(send_buf, adc_buf, sizeof(adc_buf)); adc_dma_done 0; __enable_irq(); // 拼帧并通过串口DMA发送 uint8_t frame[32]; uint16_t len build_frame(frame, send_buf, ADC_CHANNEL_COUNT); HAL_UART_Transmit_DMA(huart2, frame, len); } }最容易被忽略的是临界区保护。DMA是循环模式会不停地把新数据写到数组里。如果主循环中还没有拷贝完DMA已经写入了下一轮数据那读到的就是新旧交错的数据。所以拷贝前要关闭中断或者用双缓冲方案。数据修正方面G474的12位ADC结果左对齐还是右对齐取决于CubeMX里Data Alignment的设置默认右对齐所以无符号范围内就是0到4095。如果你采集的是双极性电流信号会有偏置电压比如1.65V需要先把原始值换算成电压再减去偏置最后标定成实际电流。这个过程不要放在中断里做放在主循环统一处理即可。3.3 怎么验证采样点真的在PWM中间代码写完不能直接说“应该没问题”必须用示波器验证时序。手头如果没有高端设备有一个简单实用的验证方法把HRTIM的ADC触发源再映射到一个空余GPIO上某些HRTIM配置允许把触发信号引到引脚或者你可以直接把PWM输出和ADC触发点用逻辑分析仪对比然后在引脚上输出一个脉冲信号作为标记。更常见的做法是用示波器的两条通道通道1接PWM输出通道2接电流采样点。然后在代码里每次ADC转换完成时翻转一个GPIO。如果翻转点确实出现在两个PWM边沿的正中间说明采样窗口卡对了位置。如果翻转点靠近PWM边沿就需要微调触发事件的选择或者在HRTIM里增加延时值。我自己的习惯是再把串口打印的数据和示波器波形做一次交叉验证。比如给电路注入一个直流电流看串口读到的数值与万用表实测是否一致。两者能对上说明整个链路没有问题如果差很多就要回头检查偏置是否消除干净或参考电压配置是否正确。4. 踩坑实录与排查技巧4.1 常见问题速查表现象可能原因解决办法ADC数据一直是0HRTIM的ADC触发源没启动检查是否调用HAL_HRTIM_ADCTrigStartADC数据偶尔跳变巨大采样点离PWM边沿太近改用PER事件作为触发或调整占空比窗口DMA搬运的数据错位DMA数据宽度与ADC寄存器不匹配检查Half Word/Word配置逐通道核验串口打印乱码波特率不匹配或帧格式不统一统一波特率检查帧头和帧尾约定多个通道数值互相串扰采样时间太短信号源内阻大增大采样周期或加前置运放缓冲这几种问题里最多的是“数据错位”。因为DMA是按顺序把规则组结果搬进缓冲区的如果通道顺序配置改动过缓冲区里的对应关系就会全部乱掉。排查时先在固定输入电压下打印各个通道的值看哪个值应当对应哪一路而不是直接默认数组顺序。4.2 几条独家避坑经验不要过度追求所有时刻都采样。有些应用会想着在PWM周期的上半个周期和下半个周期各采一次然后做平均。但你要知道如果两次采样分别落在不同开关状态窗口采样到的信号完全不是同一个东西平均反而会把信息搞乱。对于大多数电流采样应用一个PWM周期采一次就够了。还有个很容易踩的坑是看门狗在调试期间被饿死。当你把全程改成DMA 主循环轮询后循环速度有可能非常快也可能偶尔卡在某个等待操作上。如果开了IWDG建议调试阶段先把它关掉等整套逻辑稳定后再打开否则很容易出现“程序莫名其妙重启”的假象。另外关于串口打印速率永远要算一笔账。假设20kHz采样率每周期采4路ADC每路数据占2字节加上帧头和校验开销一秒钟产生的数据量差不多有200KB。对应波特率至少要2Mbps以上。如果波特率不够就得在代码里做降采样比如每10个PWM周期才通过串口发一次数据或者只打印计算后的结果而不打印原始值。这个很多人一开始没算等波形刷新一卡才发现带宽不够。最后再说一个硬件层面的小建议ADC采样引脚不要直接长距离连到功率级建议加一级RC低通滤波器截止频率设置在开关频率的1/10左右。这样既能进一步滤除残余高频噪声又不会明显影响信号带宽。RC参数选型时要注意RC太大采样建立时间会变长跟ADC采样时间配合不好反而会引入误差。配套测试下来1k欧加1nF是比较实用的起步组合。这套方案整体调通之后你会明显感觉到采样数据的质量比“随手触发”好太多串口打印出来的波形干净而稳定。如果你正好也有类似的需求直接把配置照抄一遍再根据自己的电路拓扑调整触发事件和采样窗口大概率一次就能跑通希望这篇笔记能帮你省掉相当一部分调试时间。本文还有配套的精品资源点击获取
返回列表