ARTICLE DETAIL

资讯详情

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

STM32数字电源设计:ADC采样、互补PWM与硬件保护实战解析

STM32数字电源设计:ADC采样、互补PWM与硬件保护实战解析 做数字电源这几年我有一个很深的感受很多人拿到STM32的第一反应是先跑个LED、点个屏但真正把这片芯片用在功率控制上时才发现它最值钱的地方根本不是CPU主频而是一整套为实时控制服务的外设组合。数字电源设计和普通MCU应用最大的区别在于你面对的不再是逻辑对不对的问题而是时序准不准、采样抖不抖、保护快不快的问题。这篇内容我会围绕STM32在数字电源里最关键的几个外设——ADC采样链路、高级定时器PWM、比较器/DAC保护和调试中的实际问题展开把每个外设为什么这么用、怎么配、配完会遇到什么坑都讲清楚适合正在做数控电源、DC-DC或者电池充电器的工程师也适合刚入行想搞懂数字电源到底数字在哪的开发者用来建立整体认知。1. 为什么数字电源绕不开STM32从模拟补偿到数字环路的本质变化1.1 数字电源到底数字在哪控制环路已经跑进MCU传统模拟电源的环路是靠运放、电阻、电容搭出来的。输出电压反馈回来经过误差放大器和RC补偿网络直接和三角波比较产生PWM。整个过程是连续时间的模拟信号处理你很难在不改硬件的情况下调整环路参数温度变化还会让电容容值漂移补偿曲线跟着变。数字电源的思路完全不同。输出电压经过电阻分压后进ADC变成数字量MCU里跑PID算法算出差值最后更新定时器比较寄存器改变占空比。也就是说模拟电源里那个由硬件决定的补偿网络在数字电源里变成了由代码决定的控制算法。你改一个kp、ki、kd环路特性就变了不用动一颗电阻。这里有个很多初学者容易忽略的点数字电源的数字不是指用屏幕显示电压电流而是控制环路的核心计算都在MCU内完成。你仍然需要模拟电路来处理信号调理和功率驱动但决策链路已经全部数字化。这就是为什么敢说数字电源绕不开MCU——没有MCU就没有环路计算的地方。1.2 市场导入期的选型逻辑为什么团队最终都看向STM32从近几年的电源产品需求看数字电源已经不是实验室里的玩具了。服务器电源、通信电源、充电桩模块、车载OBC都在往数字控制方向走。原因很简单客户要求效率更高、动态响应更快、通信接口更丰富还有生产端的一致性要求——模拟方案的零散器件太多每颗料都有误差调试成本很高数字方案把环路参数固化在固件里一致性天然就好。那为什么选STM32而不是其他MCU我用过好几个厂家的片子最终留在STM32上的原因可以总结成三点。第一是产品线覆盖足够宽。从最基础的F103到专门为数字电源设计的F334、G4系列同一个内核生态、同一套开发工具项目不同阶段可以平滑迁移。你用一个入门级项目验证完算法到了量产阶段想换更高性能的片子不需要把代码推倒重来。第二是CubeMX和HAL库把外设初始化门槛降得很低。数字电源涉及ADC、DMA、定时器、比较器、DAC这好几个外设的联动如果用寄存器一个个配光初始化就要一周CubeMX图形化配置后重点就变成了算法和时序逻辑本身。第三是关键外设确实齐全。高级定时器能输出互补PWM带死区ADC支持外部触发和DMA搬运F334和G4系列内部还集成了比较器、DAC、运放——这些东西在数字电源里几乎是刚需。后面我会逐一展开。2. 采样链路是环路的眼睛ADC通道规划与时序同步2.1 通道布局电压、电流、母线、温度怎么分配数字电源的ADC采样对象通常包括输出电压、电感电流、输入母线电压和功率器件温度。每一个采样对象对ADC通道的要求都不一样不能随便往一个通道上一接了事。输出电感和输出电压的分压网络源阻抗一般在几kΩ到几十kΩ之间。源阻抗越高ADC内部的采样电容充电就越慢需要的采样时间就越长。如果你的分压电阻用了两个100kΩ那ADC采样时间不能设太短否则采到的值会偏低——不是信号真的低了是电容还没充满就被切走了。电感电流的采样方式就更有讲究了。用采样电阻运放是常见做法这时候运放的带宽、摆率和ADC采样时序要匹配。还有用电流互感器或者霍尔传感器的输出信号特性和采样电阻完全不同。互感器输出的是电流信号通常要并一个电阻转成电压霍尔传感器有零漂需要软件校准。温度采样比较简单NTC热敏电阻分压后进ADC。但NTC的响应速度很慢没必要每周期都采放到低速任务里处理就行。这正好体现了通道分组规划的价值——高速通道管环路低速通道管监控。我自己在Buck电路项目里常用这样的通道分配采样对象ADC通道采样速率用途输出电压IN0开关频率电压环反馈电感电流IN1开关频率电流环反馈/过流监控输入母线电压IN2低频1kHz前馈/欠压保护功率管温度IN3低频10Hz过温保护这个表的核心思路是环路相关信号必须高速高优先级监控类信号低速低优先级。如果所有通道都按开关频率采样DMA缓冲区会很大MCU在每周期中断里要处理大量无关数据白白浪费CPU时间。2.2 让采样时刻对准开关中点用PWM的TRGO触发ADCADC采样的时刻是数字电源最关键的时序问题之一。很多第一次调数字电源的人都会遇到这样的现象PID的参数怎么算都对但实际波形就是稳不住输出电压上叠加了一大堆毛刺。这一般不是PID的问题而是采样点落在了开关噪声里面。功率管开关的瞬间di/dt和dv/dt都很大会在地弹和采样回路上耦合出很高的噪声尖峰。如果ADC在这个瞬间采样采到的值就带上了大量高频干扰环路看到的是一个假的反馈量自然会把占空比调错。解决思路是让采样时刻避开开关沿。最常见也最有效的做法是用PWM定时器的TRGO信号去触发ADC转换。在Buck电路里开关管导通时电感电流上升关断时下降电流波形在开关周期的中间点最平稳。你可以把PWM的定时器配置成在计数到中点时输出TRGOADC收到这个触发信号后开始采样。这样每次采样点都自动落在开关周期的中心噪声最小。用STM32CubeMX配置时你需要在TIM高级定时器的Trigger Output (TRGO)选项里选择Update Event或者OC1REF等触发源具体取决于你想要的触发相位。然后进入ADC配置把ADC_Regular_ConversionMode里的External Trigger Conversion Source选成你那个定时器触发边沿选Rising Edge。这样ADC就完全由PWM同步触发不需要任何额外中断。这个方案还有一个额外好处采样时刻和PWM周期严格同步环路计算出来的占空比更新到寄存器后下一个周期就生效控制延时可预测这对环路稳定性分析特别重要。2.3 DMA搬运和数据对齐把乱序采样变成规整数组多通道扫描模式下ADC一次扫描下来输出寄存器里交替出现的是不同通道的数据。如果在中断里挨个读ADC1-DR读完了还要判断当前是哪个通道代码很容易写乱而且频繁进中断也会影响控制环路的实时性。标准做法是开启DMA循环模式。配置ADC为Scan模式加Continuous或者External Trigger模式DMA设置为Circular数据缓冲定义成一个数组例如uint16_t adc_buf[4]。ADC每转换完一个通道DMA会自动把结果存进数组对应的位置不需要CPU干预。你只需在DMA传输完成中断里拿数组里的数据去算PID。这里要注意数据对齐。STM32的ADC是12位的转换结果存在16位寄存器里的高12位或者低12位取决于对齐配置。我的习惯是选右对齐这样DMA搬出来的uint16_t值可以直接乘比例系数换算成实际电压不用做位运算。另一个容易忽略的细节是DMA缓冲区大小和ADC转换通道数的匹配。如果ADC配了4个通道DMA缓冲区长度就要配4。一旦不匹配轻则数据错位重则DMA越界写坏内存。曾经在一次项目里我配了3个ADC通道但DMA长度设成了5结果缓冲区末尾的两个位置被当成其他变量的地址程序跑起来整个数据链路都是乱的查了很久才发现是这种低级问题。3. 功率级是环路的双手高级定时器的互补PWM与死区3.1 互补输出和死区配置Buck半桥最基础的一步数字电源的大多数拓扑——同步Buck、半桥、全桥、LLC——都需要互补PWM驱动上下管。上下管交替导通但如果上管还没完全关断下管就导通了这就是直通会直接炸功率管。所以硬件设计里必须留出死区时间也就是上下管都关闭的那一段空白期。STM32的高级定时器TIM1和TIM8内部集成了死区生成电路。你只需要配置一个通道的互补输出硬件会自动在上下管切换时插入死区。在CubeMX里配置PWM Generation CH1和CH1N然后在Break and Dead Time里填死区时间。注意这里单位是定时器时钟周期不是纳秒。比如定时器时钟是72MHz一个时钟周期是13.9ns你要100ns死区需要填的数字大约是7或者8。死区时间设置是有讲究的不是越大越好。死区太小功率管关不断就开通直通炸管死区太大占空比丢失明显效率下降输出纹波变差。实际取值要看功率管栅极电荷和驱动电阻决定的开通关断时间。我的一般经验是先用示波器看实际波形把死区调到开关管完全关断后留出20%~30%的余量。这里特别提醒有些国产替代芯片或者新版Cortex-M内核的定时器死区寄存器格式有细微差别CubeMX生成的代码一般没问题但如果手动写寄存器务必对照参考手册确认DTG字段的编码格式。3.2 频率与分辨率怎么取舍定时器参数的计算过程数字电源的PWM频率通常在50kHz到500kHz之间。PWM频率越高电感和电容的体积可以越小动态响应越快但开关损耗也越大。选择PWM频率之后定时器计数时钟和自动重装载值ARR就决定了占空比分辨率。计算公式是PWM频率 定时器时钟 / ((PSC1) × (ARR1))。占空比分辨率 1 / (ARR1)或者说占空比可调的步进量是1/(ARR1)。举个实际例子STM32F103的高级定时器挂在APB2总线上时钟72MHz。如果用50kHz PWM不分频PSC0ARR1439。这时占空比分辨率为1/1440大约是0.07%。对于大多数Buck应用来说这个分辨率够用输出电压纹波可以控制在几十mV以内。但如果你要做一个输出电压精度要求很高的电源例如0.1%的稳压精度0.07%的占空比分辨率在低占空比时就不太够用了。这时候只有两条路一是降低PWM频率提高分辨率二是换带高分辨率定时器的型号。STM32G4和F334的HRTIM能把PWM边沿分辨率做到几百ps级别相当于理论上无限细分占空比这对高精度数字电源是质的提升。在配置时还要注意PSC和ARR之间的配合。有时候你会发现同样的PWM频率PSC设成1和设成2都能得到近似值但分辨率不一样。原则是优先保持ARR尽量大PSC尽量小这样占空比步进最小。3.3 刹车功能硬件级封锁PWM比什么软件都快数字电源的故障保护分为两级软件保护和硬件保护。软件保护是ADC检测到过压、过流后在中断里把PWM占空比清零或者直接关闭输出。但CPU执行中断需要时间从故障发生到软件反应一般有微秒级的延迟。对于短路这种瞬态故障微秒级延迟就可能烧毁功率管。高级定时器的刹车Break功能就是为了解决这个问题。你可以把比较器的输出、驱动芯片的故障信号或者应急开关接到BKIN引脚上一旦引脚电平跳变定时器硬件立即封锁PWM输出不经过CPU延迟在纳秒级。同时还能配置自动刹车和恢复模式刹车条件解除后由软件控制恢复输出。我做过一个48V转12V的同步Buck电流采样经过片内比较器比较器输出直接连到BKIN过流阈值由DAC设定。第一次做短路实验的时候心里很没底结果示波器显示从短路发生到PWM封锁只用了不到200ns功率管温度一点没升。这个保护速度是软件无论如何都做不到的所以数字电源设计里硬件保护通道不是可选项而是必选项。4. 比采样更快的那道保险片内比较器、DAC与模拟看门狗4.1 比较器DAC参考电压微秒级过流关断前面提到的刹车功能触发信号从哪来最常见的是片内比较器。STM32G4和F334内置了多个高速比较器正输入端接电流检测信号负输入端可以由内部DAC输出一个参考电压。当电流检测电压超过DAC设定的阈值时比较器输出翻转这个翻转信号可以直接送到定时器的刹车输入实现硬件级保护。这个链路的好处是不用ADC采样不用CPU参与阈值还可以用DAC软件调整。电流限制值想改多少改一下DAC的数值就行不用换电阻。这在产品批量调试时特别方便每台设备的电流保护点都不用重新校准硬件。需要注意比较器的输入范围。STM32片内比较器的输入电压范围不能超过VDDA如果电流检测信号是负压或者超过电源轨需要做电平转换或者在使用外部比较器后把信号整形。另外比较器输出有传播延迟大约是几十纳秒这对绝大多数电源应用来说完全够用。4.2 模拟看门狗给ADC数据加一道软件保护网片内比较器负责硬件快速保护模拟看门狗AWD则负责软件层的阈值监控。STM32的ADC自带模拟看门狗功能可以对指定通道设置上限和下限当转换结果超出范围时自动产生中断。这个机制比你在中断里手动比较数值更可靠因为它完全由ADC外设硬件检查即使主程序正在忙别的事情也不会漏掉超限事件。数字电源里模拟看门狗我一般用在这几个地方输入母线过压、输出电压过压、输出电压欠压。每个通道的上下限可以根据实际工况设置超限后在中断里执行故障处理逻辑比如记录故障标志、关闭输出、点亮告警灯。这里有个经验模拟看门狗的中断不要在中断里做太多事情。中断里只置故障标志和关闭PWM输出具体故障分析、通信上报放到主循环或者RTOS任务里。否则中断处理时间过长可能错过下一次看门狗事件或者影响控制环路的实时性。4.3 外设选型速查F1/G4/F334在数字电源上的差异总有人问我能不能用F103做数字电源。能用但局限很大。我把几个常见系列的差异列个表方便你选型特性STM32F103STM32F334STM32G4系列主频72MHz72MHz170MHz高级定时器TIM1/TIM8TIM1 HRTIMTIM1/TIM8部分含HRTIM片内比较器无有有片内DAC部分型号有有有片内运放无有PGA有数学加速器无无CORDICFMAC适合场景学习验证数字电源专用入门中高端数字电源F103的ADC没有外部触发采样不F103的ADC支持定时器触发做同步采样是可以的但缺少片内比较器和运放硬件保护必须靠外部芯片电路复杂度和成本都会上升。F334是我比较推荐的第一颗数字电源专用芯片它的HRTIM和内置比较器能让你用最简单的外围电路实现一个功能完整的数字电源。G4系列则适合需要运算复杂算法比如无桥PFC、多相交错或者需要同时处理多路电源的项目。5. 实际调试中踩过的几个外设坑5.1 采样点没对准PID越调越震荡这个坑我印象太深了。第一次调数字电源的时候PID参数是从模拟电源的补偿网络换算过来的算出来应该很接近结果一上电输出波形就是震荡的频率大概在几千赫兹和开关频率完全不搭。那时候我还以为是PID参数算错了把参数来回改了好几轮问题依旧。后来用示波器同时抓了开关节点波形和ADC采样值才发现我配置的ADC触发沿正好落在开关管开通的瞬间采样值里全是振铃噪声。把触发点改到PWM计数中间之后输出纹波立刻从几百mV掉到几十mVPID参数几乎不用怎么改就稳了。这个经验说明数字电源调试先解决时序再调参数。采样点不对再好的控制算法也会被噪声带偏。你在排查环路不稳定问题时第一步永远是看采样波形干不干净而不是直接动PID。5.2 多通道扫描下的通道串扰还有一次踩的坑更隐蔽。我的ADC扫描里有一个通道接了NTC温度传感器它的源阻抗很高采样时间我设得比较短结果温度读数偏高。后来发现温度通道前面的一个通道是电感电流采样电流信号变化很快残余电荷还没来得及放完就被采样电容采走了导致了串扰。STM32的ADC内部有一个采样电容每个通道转换之前这个电容要先连接到上一次的通道上充电然后断开再连接到当前通道。如果上一次通道的信号是小电流、高阻抗下一次要采样高阻抗的NTC串扰就会非常明显。解决方案有两个一是给高阻抗通道加一个跟随器降低源阻抗二是在CubeMX里给慢速通道单独设置更长的采样时间。ADC的采样时间是可以逐通道配置的不用为了一个慢速通道把整个ADC都拖慢。5.3 死区只是看起来配了直通才是真凶死区配置的坑往往出在你说不清是软件问题还是硬件问题上。我调试半桥的时候驱动波形单看上下管都是对的但功率管温度异常高效率也上不去。用示波器一放大看切换沿发现上管的关闭下降沿很缓和下管的开启上升沿之间有明显重叠——虽然死区时间配了但上管因为栅极电阻太大关断速度太慢在死区结束之前还没完全关断。死区时间的配置不能只看寄存器数值要结合实际开关速度去看。上管关断慢就要加大死区或者减小栅极驱动电阻。在项目里我一般会让硬件预留不同的栅极电阻焊盘调试时根据实际波形选择合适的值然后再回头确认死区配置。这个先看波形再定参数的顺序不要搞反。5.4 环路周期到底该跑多少由PWM中断决定还是DMA决定最后一个问题也是很多初级工程师容易纠结的PID计算应该放在哪个中断里执行我自己最后确定的方案是环路计算放在ADC的DMA传输完成中断里因为DMA传输完成意味着最新一轮采样数据已经就绪这时候算PID拿到的反馈量是最新的计算完立刻更新比较寄存器延迟最小。不要放到定时器更新中断里。定时器更新中断只是代表PWM周期到了但这时候ADC的最新数据可能还没转换完你拿到的采样值是上一轮的控制延迟就增加了一整个采样周期。如果是多通道扫描通道越多延迟越明显。环路延迟增加会降低相位裕度对系统稳定性非常不利。另外如果你在项目里用了RTOS比如FreeRTOS管理显示和通信任务我建议环路计算仍然留在中断里RTOS任务里只做非实时的事情。控制环路在裸机中断里跑避免了任务调度带来的抖动。这是我调试过好几个项目总结出的稳妥做法。写到这里我想到这两年做数字电源项目最有价值的体会其实就一句话STM32的外设不难配难的是理解每个外设为什么存在、它和整个系统怎么配合。你花时间把采样时序、互补PWM、硬件保护这条链路吃透后面调任何拓扑、任何控制算法都会顺畅很多。
返回列表