ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PWM做DAC的纹波抑制全攻略:从RC滤波到有源滤波实践

PWM做DAC的纹波抑制全攻略:从RC滤波到有源滤波实践 用PWM做DAC这件事表面看就是“定时器翻转IO加一个RC滤波”但真正在项目里用起来纹波、过冲、带载能力、响应速度这些坑一个接一个。很多朋友在STM32、ESP32、树莓派上做PWM转模拟量示波器一接波形上全是毛刺和振荡尤其中间再夹一个LC滤波或者高Q值有源滤波上升沿直接给你来一个过冲振铃看着就头大。这篇文章就把PWM DAC纹波抑制这件事从头到尾捋一遍从公式到计算从一阶RC到有源滤波从配置到测量按我做过的项目经验来写希望能帮你少走点弯路。1. 纹波从哪来PWM做DAC的底层逻辑1.1 PWM做DAC为什么能行PWM转模拟电压的核心逻辑是平均值等效。一个周期内高电平持续的时间占整个周期的比例叫占空比D那么经过低通滤波后输出端的直流电压近似等于高电平电压乘以D。这个逻辑很简单但背后有两个前提第一滤波器的截止频率要远低于PWM的基频第二负载不能把滤波器的“平均效果”破坏掉。很多人在这里容易犯一个认知上的偏差以为PWM本身就是“模拟输出”。其实PWM引脚输出的还是数字方波只有经过滤波之后才是真正的模拟信号。分辨率取决于定时器/计数器的位数8位是256级12位是4096级16位就是65536级。位数越高理论上可以输出的电压台阶越细。但注意在MCU时钟频率固定的情况下分辨率和PWM频率之间存在直接矛盾后面会详细算。为什么这么多人会选PWM做DAC而不是直接用一颗DAC芯片原因很简单成本和引脚。一个定时器引脚只要几毛钱而一颗16位高精度DAC芯片可能要十几块甚至几十块。对于精度要求不是极端苛刻、更新速率不高的场景比如LED调光、风扇控速、电压基准粗调、电机给定值输出PWM加滤波完全够用。这也是它长期霸榜“低成本模拟输出方案”的原因。1.2 纹波怎么算一阶RC模型要抑制纹波先要知道纹波是怎么产生的。以最基础的一阶RC低通滤波为例PWM高电平期间电容通过电阻充电电压上升PWM低电平期间电容通过电阻放电电压下降。当这个充放电过程达到稳态后电容上的电压会在一个平均值附近上下波动这个波动的峰峰值就是纹波。工程上最常用的近似公式是ΔV ≈ VH × D × (1 - D) × T / (R × C)其中VH是高电平电压D是占空比T是PWM周期RC是滤波器时间常数。这个公式的推导思路是稳态时导通期间充入的电荷等于关断期间放掉的电荷。导通期间充电电流近似为(VH - Vout)/R充电时间D×T关断期间放电电流近似为Vout/R放电时间(1-D)×T。把Vout近似为D×VH联立就能得到上面这个结果。我来算一个具体例子。VH5VD0.5PWM频率10kHzT100usR1kΩC10uF。代入公式ΔV ≈ 5 × 0.25 × 100us / (1k × 10uF) 0.125V也就是125mV。这个纹波相当大了如果目标是10mV以内就必须把时间常数RC提高到12.5ms以上或者把PWM频率提上去。从这个公式能很清楚地看到三个抑制纹波的杠杆杠杆效果代价提高PWM频率纹波随T等比例下降高分辨率与频率矛盾MCU开销增加加大R×C纹波随RC等比例下降响应变慢带载能力变差提升滤波器阶数谐波衰减更快电路复杂度、成本、相位延迟增加1.3 纹波的频谱视角用频域视角再看一遍纹波本质是PWM方波中的开关频率及其谐波分量没有滤干净。滤波器不是“消除”高频而是“衰减”高频。一阶RC在截止频率之后按20dB/十倍频程衰减基波衰减量约等于f_PWM / fc。比如PWM频率20kHz滤波器截止频率1kHz则基波衰减约20倍也就是26dB左右。这个衰减量看似不小但由于方波的基波分量本身幅度很大剩余的能量依然可能造成明显的纹波。二阶滤波器是40dB/十倍频程同样20kHz对1kHz理论衰减约40倍效果就好很多。不过这里有两个隐藏问题第一滤波器阶数越高在截止频率附近的相位延迟越大对阶跃响应的影响越明显第二非理想元件电容ESR、电感饱和、运放带宽会限制高频衰减的实际效果。所以工程计算时不要只盯着理想衰减曲线最好留出3到5倍的裕量。2. 滤波器设计与元件选型实操2.1 一阶RC的参数计算与元件选择做一阶RC设计时先定目标纹波再反推时间常数。举个例子单片机输出5V PWM频率10kHz希望输出纹波小于10mV占空比按最恶劣的50%算。需要的RC ≥ VH × 0.25 × T / ΔV 5 × 0.25 × 100us / 0.01 12.5ms。如果我选R1.2kΩ、C10uFτ12ms理论纹波约10.4mV差不多贴着目标线走。想更稳一点就选R1.5kΩ、C10uFτ15ms。元件选型有几个容易踩的坑。电阻值不能选太大。很多人为了省电流把R加到100kΩ以上结果后端ADC或下一级电路的输入阻抗只有几十千欧分压效应直接把输出电压拉偏了。一般R取1k到10k之间比较合适后端必须接高阻抗负载或运放缓冲。电容要注意类型推荐X7R或C0G陶瓷电容。X7R的容量温度稳定性尚可C0G更好但大容量的贵普通电解电容ESR偏大在PWM纹波抑制这种场景下虽然也能用但高频特性不如陶瓷电容如果同时存在高频噪声纹波实测值会比理论值大。还要留意MLCC的直流偏压特性小封装的10uF电容在5V偏压下实际容量可能只剩6到7uF计算时要留裕量。2.2 二阶低通与RCRC级联的注意事项如果一阶滤波不够很多人自然会想“我再加一级RC”。这个思路本身没问题但直接做R1C1串R2C2是有讲究的。如果不加缓冲第二级的输入阻抗会“加载”到第一级的输出上导致第一节的有效截止频率被抬高实际衰减曲线和理想二阶曲线差得很远。常用的解决办法有两个要么让R2远大于R1比如10倍以上弱化加载效应要么在两级之间加一个运放电压跟随器做隔离。另一个比RCRC更常见但更危险的做法是RC后面直接接LC或者干脆用LC滤波。LC滤波的衰减特性确实好但它的阻尼特性由电阻和负载决定如果电感内阻很小、负载又轻回路Q值会很高在PWM跳变沿的激励下会产生明显的欠阻尼振荡。这就是很多人提到的“dac输出方波上升有过冲振荡、下冲振荡”的典型来源之一。要抑制这种振荡最简单的是在电感上并联一个几十到几百欧姆的阻尼电阻或者串联一个小电阻降低Q值。但阻尼电阻会引入额外损耗输出电压精度也会受影响所以LC在PWM DAC里用起来并不舒服我更推荐有源RC方案。2.3 有源滤波与运放缓冲有源低通滤波是PWM DAC里最“顺手”的方案典型结构是Sallen-Key二阶低通加一级电压跟随输出。这个结构的好处有三点第一运放输入阻抗高前面RC网络不被负载加载第二运放输出阻抗低后端接ADC、接下一级电路都很稳第三可以通过电阻电容比值控制Q值做到巴特沃斯特性既没有过冲又比单纯RC级联更陡峭。设计Sallen-Key二阶低通时核心参数是两个截止频率fc和品质因数Q。巴特沃斯响应对应Q0.707这是最常用、也是我推荐多数场景优先选用的值。如果Q大于0.707幅频响应会在截止频率附近隆起阶跃响应就会有过冲。很多“上升沿振铃”的问题就是设计时没控制Q值。选运放时不用追求太高带宽PWM滤波这种低频场景GBW在1MHz左右就够反而要关注输入偏置电流、失调电压和噪声。普通LM358、TL072、OP07都能用要求低噪声就选OP07或NE5532级别的。给运放供电一定要做去耦电源引脚附近放100nF陶瓷电容加10uF钽电容或电解电容否则电源噪声会直接串进输出。3. 常用MCU平台配置与实战场景3.1 STM32定时器PWM输出配置STM32做PWM DAC是最常见的场景之一以F103为例它挂在APB1或APB2总线上的定时器时钟通常可以到72MHz。PWM频率和分辨率的计算公式是f_PWM fclk / ((PSC1) × (ARR1))分辨率位数 log2(ARR1)PSC是预分频器ARR是自动重装载值决定占空比的是比较寄存器CCR。举个例子我想输出20kHz的PWM直接用72MHz时钟不分频那么ARR1 72MHz / 20kHz 3600分辨率大约是log2(3600)≈11.8位也就是接近12位。这个分辨率对大多数控制场景足够。如果继续把这个频率推到100kHzARR1720分辨率只有9.5位电压台阶就明显了。配置时要注意几点修改ARR会改变PWM频率如果动态调整占空比的同时又改频率务必在更新事件里同步处理否则输出会突然跳变。F103的高级定时器TIM1/TIM8带互补输出和死区做H桥或者半桥驱动时要小心占空比100%的情况有些驱动芯片在占空比达到100%时会关闭输出或翻转逻辑故障保护策略要提前想清楚。如果是F334这种带HRTIM的高分辨率定时器可以用数字锁相环做到ps级别的边沿调节它更适合对占空比精度要求极高的场合但配置复杂度也高用CubeMX生成基础工程后主要精力要放在同步和触发关系上。STM32的PWM输出引脚本身驱动能力有限别直接用一个很大的电容做滤波后接负载。IO翻转边沿变缓之后定时器输出级的动态功耗会上升而且数字噪声会耦合到模拟信号上。规范做法是PWM引脚出来先接滤波网络再接运放缓冲最后输出给负载。3.2 ESP32的LEDC高频PWM配置ESP32做PWM模拟输出很多人会想到它的内置DAC其实ESP32的DAC只有8位精度和线性度一般而且温漂明显很多场合反而不如“PWM加外部滤波”来得实在。ESP32的LEDC外设支持设置分辨率和频率关键公式是f_PWM clk / 2^bitsclk通常取80MHz。如果你要12位分辨率频率就是80MHz / 4096 ≈ 19.5kHz。要8位分辨率频率可以到312.5kHz纹波抑制压力会小很多。我见过不少人在ESP32上做空心杯电机控制用ledcAttachPin、ledcSetup、ledcWrite这三个函数但没注意分辨率和频率的换算关系设了16位分辨率后发现PWM频率只有1.2kHz电机嗡嗡响纹波大得一塌糊涂。实际经验是电机调速这种场景8到10位分辨率足够频率尽量提到20kHz以上超过人耳可听范围还能减少噪音。ESP32的LEDC还有一个特性高分辨率模式和高频率模式可以配合“抖动”来提升有效精度类似sigma-delta的思想但实现复杂度较高普通应用不必碰。如果你需要真正的多通道高精度模拟输出比如十几路信号同时输出那PWM加滤波的规模和成本会迅速上升这时候就该考虑外部专用DAC芯片了。3.3 PCA9685等外部PWM芯片与独立DAC的取舍PCA9685大家用得很多16路12位PWM输出I2C控制但它的PWM频率通常只有40Hz到1000Hz这个频率对电压纹波非常不友好。算一下就知道如果用1kHz PWM要获得10mV以下的纹波一阶RC需要的时间常数是125ms响应速度完全没法看就算用二阶滤波要衰减到同样水平截止频率也得压到几赫兹典型的“调得稳但慢如蜗牛”。所以PCA9685直接做DAC的方案我基本不推荐除非你的负载对纹波不敏感比如LED亮度控制。如果确实需要多通道高精度模拟输出我更建议直接上独立DAC芯片比如MCP4725、DAC8571、AD5662这些。12位和16位都有更新率比PWM滤波方案高好几个数量级而且不需要为每个通道配一堆RC和运放。成本上单颗DAC芯片虽然比一个引脚贵但折算上运放、电阻、电容、PCB面积和调试时间在通道数多的时候反而更划算。方案优势劣势适合场景MCU PWM RC滤波成本极低实现简单响应慢纹波较大单路、低速、粗精度MCU PWM 有源滤波纹波可控带载能力强需要运放成本中等中等精度比如电机给定、电源反馈独立DAC芯片精度高更新快多通道成本高需要I2C/SPI驱动多通道、高精度、动态响应要求高3.4 FPGA任意波形发生器中的PWM/DAC滤波FPGA场景下很多人用高速PWM或者sigma-delta输出配合外部重建滤波器做任意波形发生器。这时候的滤波设计和MCU低速场景有个很大的区别波形本身的带宽不再是几十赫兹而是可能到几十千赫甚至更高。如果重建滤波器的截止频率设得太低输出波形的高频分量会被削掉方波变圆弧设得太高PWM的开关纹波又压不住。设计时要以“信号带宽”为基准先确定最大的信号频率再反推PWM频率至少要给到信号频率的10到20倍滤波器截止频率放在两者之间。FPGA里同时要处理好时钟抖动抖动会直接转化为输出波形的噪声做高精度波形时这个影响非常明显。4. 示波器实测与疑难排查4.1 上升沿过冲振荡的根因与排查“PWM DAC输出方波上升有过冲振荡”这个问题被问过太多次了但我每次仍然建议先别急着改电路先确认振荡到底是真实信号还是测量假象。用示波器测高频振铃时如果探头地线用的是那种十几厘米长的鳄鱼夹地线探头本身的电感和地线电感会和被测电路形成谐振常见的几MHz到几十MHz振铃很多都是这么“测出来”的。正确做法是用接地弹簧尽量缩短地线回路。如果接上弹簧后振铃明显变小或者消失那恭喜你电路本身没问题。如果确实是真实过冲按下面这个顺序排查先断开后级负载只看滤波网络本身的阶跃响应。如果空载时依然过冲问题大概率在滤波器自身。对于LC滤波是Q值过高对于有源二阶滤波是Q值设置偏大把Q降到0.707以下或者增大反馈电容。如果空载正常但接上负载就振铃那就要看负载性质。容性负载会让运放相位裕度下降比如运放输出直接接一个大电容很多通用运放都会不稳定解决方法是输出串一个小电阻几十欧再连电容或者选用容性负载能力强的运放型号。还有一种情况是PWM信号本身从MCU引脚出来就有振铃尤其引脚走线比较长、驱动速度很快的时候。这时候滤波网络前端就已经带上了高频噪声后级怎么滤都不干净。解决方法是降低IO翻转速率很多MCU引脚有 slew rate 控制或者先串一个22Ω到47Ω的电阻做源端匹配。4.2 示波器测量的三个陷阱测量PWM DAC输出纹波时有几个操作细节直接影响你看到的数据可信度。带宽限制。示波器默认全带宽显示很多高频噪声其实和PWM DAC纹波无关。测低频纹波时建议打开20MHz带宽限制把无关的高频尖峰滤掉再看。探头输入电容。普通无源探头输入电容大概10到15pF如果被测点输出阻抗很高这个电容会形成一个低通滤波甚至谐振改变你看到的波形。测量时尽量用1x或10x探头注意探头补偿是否校准。对于高阻抗节点有条件就用有源探头或者至少用示波器内置的带宽限制功能辅助判断。接地方式。地线夹过长的问题前面说过了这里再强调一遍测纹波时把探头地线夹换成弹簧地或者直接在探头尖端边上焊一根短地线效果完全不一样。我调试过程中有好几次“电路有过冲”的结论最后都是因为地线方式改了就消失。4.3 常见问题速查表现象可能原因排查方法解决思路纹波过大RC时间常数不足、PWM频率太低、滤波阶数不够示波器分别测滤波前/后波形对比提高PWM频率、增大RC、升级为二阶/三阶滤波上升沿过冲振荡LC或高阶滤波器Q值过高、运放带容性负载不稳定断开负载看空载波形、检查阻尼电阻增大阻尼、降低Q值、输出串隔离电阻输出带载后电压跌落滤波电阻过大、负载阻抗太低测不同负载下的输出电压加运放缓冲隔离减小R响应太慢滤波器截止频率压得过低给PWM一个阶跃量建立时间提高PWM频率用更高阶滤波代替一味压低截止频率输出电压抖动不规律电源纹波、地弹、PWM抖动示波器看电源轨与输出波形对比加强电源去耦、优化布线、减小地回路高频尖峰毛刺数字开关噪声、测量地线过长开20M带宽限制、换接地弹簧降低IO翻转速率、加源端串阻、优化PCB走线4.4 一个实用的调优顺序建议我在实际项目里遵循的调优顺序是先把PWM频率提到系统允许的最高值大多数主频几十兆的MCU提到20kHz以上完全没问题接着用一阶RC把纹波算到目标值附近如果响应时间还能接受就停在这里如果响应时间和纹波矛盾太大再加一级有源二阶滤波并保持巴特沃斯配置最后才考虑上独立DAC。这个顺序每一步都有明确的收益和代价不容易陷入“盲目加阶数”的泥潭。还有电源去耦别忽略运放供电脚不加去耦电容再好的滤波网络也会被电源噪声毁掉。最后分享一点个人体会做PWM DAC纹波抑制最常遇见的不是“方案不行”而是“参数没算清”或者“测量没做对”。先把纹波公式吃透把一阶RC玩明白再逐步加复杂度你会发现很多问题根本不用上升到DAC芯片就解决了。如果你手头的板子正在被过冲振荡和纹波折磨不妨先确认一下测量方法再看滤波器的Q值大概率就在这两个环节里。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进