ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

PWM从LED调光到电机驱动:核心参数、定时器配置与工程避坑指南

PWM从LED调光到电机驱动:核心参数、定时器配置与工程避坑指南

玩嵌入式这么多年,PWM是我见过应用最广、却又最容易被低估的一个外设功能。从一块钱的LED闪灯驱动芯片,到几百瓦的直流电机驱动板,核心原理都是同一件事:用固定频率的方波信号,控制导通和关断的时间比例。很多人第一次接触PWM,就是调个LED亮度,觉得不过如此。等真正上手用它去驱动直流电机,才发现里面的门道远比想象的多——频率选不对电机嗡嗡叫,占空比给太小根本转不起来,驱动电路漏了续流二极管还会烧管子。这篇文章就把我从LED亮度实验开始,一路到驱动直流电机踩过的坑和经验完整梳理一遍,希望能帮刚开始玩单片机的朋友建立起一套完整的PWM知识框架。

1. PWM 的核心参数与计算逻辑

1.1 占空比:功率的“开关比例”

PWM的全称是脉宽调制,英文Pulse Width Modulation。它输出的不是什么复杂的模拟信号,就是一组高低电平组成的方波。方波的周期是固定的,但高电平持续的时间可以改变。我们把高电平持续的时间叫做脉宽,把高电平时间占整个周期的百分比叫作占空比。

比如一个周期是1ms的方波,高电平持续0.5ms,那占空比就是50%。如果把高电平时间改成0.8ms,占空比就是80%。对于纯阻性负载来说,输出到负载上的平均功率,近似等于电源电压乘以占空比。这个逻辑特别好理解——一个水龙头,一秒钟内开一半时间关一半时间,接到桶里的水,就是一秒钟内全开水量的一半。把水龙头的“开”和“关”周期设得足够短,桶里的水位就近似平稳地维持在半水状态。

实际计算的时候,占空比公式很简单:

占空比 D = Ton / (Ton + Toff) × 100% 平均电压 V_avg = Vcc × D

在单片机里,我们通常不是直接控制Ton的时间绝对值,而是通过定时器的计数寄存器来做比例控制。常见做法是:设定一个计数值上限(自动重装载值ARR),再设定一个比较值(CCR),计数器从0往上数,每计一个数的时间固定,当计数值小于CCR时输出高电平,大于等于CCR时输出低电平,反复循环。这样占空比就是 CCR / (ARR + 1)。

我用生活化的方式给你拆一下这个逻辑。假设你跑步训练,教练给你定的循环是:冲刺5秒,慢走5秒,反复进行。那么你的“高速输出占空比”就是50%。冲刺8秒、慢走2秒,占空比就是80%。PWM干的事,本质上就是教练给你安排冲刺和休息的时间比例,只不过这个比例切换速度极快,快到负载根本反应不过来,只能感受到平均效果。

1.2 频率:周期长短决定了系统表现

占空比决定“输出多少”,频率决定“这个比例多久循环一次”。对于LED调光,频率如果低于50Hz,人眼就能明显感觉到闪烁,看久了眼睛特别累。工程上一般取1kHz以上,有些高要求的场合会用到数kHz甚至几十kHz,配合光学扩散材料,肉眼完全看不出频闪。

对于直流电机,频率的选择就更有讲究了。电机内部是线圈绕组,是感性负载,电流变化会被电感“平滑”掉,所以即使PWM频率不高,电机的电流也是近似连续的波形,而不是和PWM波形一样方方正正。但频率太低的时候,比如只有几十赫兹,电机的转速会跟着PWM的开关节奏一抖一抖的,运转起来一顿一顿,扭矩输出不平稳,噪音还大。

那是不是频率越高越好?也不是。频率越高,MOSFET或者三极管的开关次数就越频繁,开关损耗显著上升。我实测过一个实验,同一个直流电机,在1kHz下驱动,MOSFET基本不发热;提高到100kHz,同样占空比下管子明显发烫,电机的效率反而下降了。所以实用中,电机驱动PWM频率一般选在15kHz到25kHz之间,一个原因是这个频率超出人耳听觉上限,没有尖锐的啸叫声;另一个原因是在这个范围内开关损耗和电流纹波能达到比较好的平衡。

这里补充一个很多新手容易忽略的问题:频率的选择和分辨率是互相制约的。如果你用定时器做PWM,时钟频率固定的情况下,频率越高,可调的占空比档位就越少。比如系统时钟72MHz,你要100Hz的PWM,计数的周期是720000个时钟,理论上你可以在0到719999之间调节占空比,分辨率非常高;但如果你要36MHz的PWM,那一个周期只有2个时钟,占空比只有0%、50%、100%三档可选。所以选频率不是拍脑袋,要根据负载特性和控制精度要求来权衡。

2. LED 亮度变化:PWM 的第一堂实践课

2.1 人眼看不见“瞬时亮度”,只记得“平均亮度”

LED调光为什么用PWM而不是直接调电压?原因很简单:LED的发光亮度与正向电流近似成正比,而对电压极其敏感。你给LED在额定电压基础上增加0.1V,电流可能翻倍,亮度突变非常剧烈,所以直接调电压很难做到平滑的亮度控制。更麻烦的是,LED的正向压降受温度影响很大,温度升高时压降降低,电流会进一步增大,严重时直接烧毁。

PWM调光则是让LED以极快的速度在“全亮”和“全灭”之间切换,通过调整点亮时间比例来改变人眼感受到的平均亮度。这个原理有点像电影放映:电影胶片实际上每秒钟只切换24帧静止画面,但人眼因为视觉暂留效应,看到的却是连续流畅的动作。LED的PWM频率足够高时(我一般建议至少1kHz以上),人眼“残留”的光感会把亮暗变化平均掉,从而形成稳定的亮度感知。

在实际项目中,我遇到过很多次因为频率过低导致LED看起来“像蜡烛一样抖动”的情况。尤其是一些驱动方案偷懒,把频率做到200Hz甚至100Hz,静态看还凑合,但如果周围有轻微震动或者人移动视线,就能明显感觉到闪烁。后来我统一把LED调光PWM频率定在2kHz,这个问题就再也没出现过。

这里还要提一下POV余晖效应的有趣应用——热词里那个旋转LED显示套件就是这个原理。LED以极快的速度切换亮灭,配合机械旋转让发光点在不同位置残留视觉影像,就能“画”出文字和图案。就像拿着发光棒在黑夜里快速挥舞,看到的是一条光带而不是离散的点。本质上,人眼的视觉暂留时间大约在0.1秒左右,所有时间低于这个阈值的快速变化都会被大脑“平滑”成连续影像。这也是PWM能骗过人眼的核心基础。

2.2 为什么 51 单片机驱动 LED 偏爱低电平

很多初学者学单片机时,第一个实验就是点亮LED。在51单片机的学习板上,你会发现一个奇怪现象——LED的正极接电源,负极接单片机引脚,要想点亮LED,程序里要写引脚为低电平。也就是说,51单片机是“灌电流”驱动LED的,而不是“拉电流”驱动。这是为什么?

这就要说到51单片机IO口的驱动能力了。以经典的STC89C52为例,P0口是漏极开路结构,内部没有上拉电阻,输出高电平时引脚处于高阻态,基本提供不了电流;P1、P2、P3口内部虽然有弱上拉,但驱动能力非常有限,大约只能提供几百微安的电流。而如果你让引脚输出低电平,IO口内部的N沟道MOSFET导通,引脚对地形成通路,外部电路可以通过引脚向地灌入电流,灌电流能力可以达到10mA以上,点亮一颗LED绰绰有余。

这个区别很关键。如果你在51上强行用高电平驱动LED,你会发现LED要么完全不亮,要么亮度极暗——因为IO口根本“推”不动这个负载。实际上,51的P0口如果要做高电平输出,必须在外部加上拉电阻,但即便加了上拉电阻,驱动能力也受限于上拉电阻的取值,通常也就几毫安。

那这和PWM有什么关系?关系大了。在51上做LED呼吸灯效果时,很多人直接写引脚翻转的延时函数,比如让引脚低电平0.5ms、高电平0.5ms,交替进行,实现50%占空比的PWM。但因为51的IO口高电平驱动能力弱,同样的占空比下,LED的平均电流比低电平驱动方式小很多,呼吸效果明显不对称。所以正确的做法是:LED阳极接电源,阴极接IO口,通过IO口控制低电平的时间比例来调节亮度,这样LED的平均电流和占空比才是线性对应关系。

顺带提一个经验:用51的硬件定时器中断来做PWM,比单纯用延时函数靠谱得多。延时函数在单片机执行其他任务时会产生累计误差,比如你延时0.1ms控制一个LED,但中断里还要处理按键扫描,时序就乱了。硬件PWM就没有这个问题,定时器独立于CPU运行,输出引脚自动翻转,完全不影响主程序的其他逻辑。

2.3 LED 驱动芯片的 FB 脚和 CS 脚:恒流调光的秘密

如果是单颗LED,用限流电阻加单片机IO口就能搞定。但在LED灯带、大屏显示等场景,单颗LED电流可能高达几十毫安甚至几百毫安,如果还用电阻限流,电阻上消耗的功率太大了,效率低还发热。这时候就需要专用的LED驱动芯片。

这类芯片通常叫恒流驱动芯片,它的核心是让流过LED的电流保持恒定,不随电源电压和LED温度漂移。芯片上常有两个关键引脚:FB(反馈)和CS(电流采样)。FB脚是电压反馈端,通过检测输出端的电压变化来调整内部功率管的导通程度;CS脚通常外接一个采样电阻,流经LED的电流会在这个采样电阻上形成压降,芯片将这个压降与内部基准电压比较,形成闭环反馈,从而恒定电流。

具体参数怎么算?我这里说一个常见的方法。比如某颗LED驱动芯片的CS基准电压典型值是0.1V,你想让LED电流为350mA,那CS采样电阻阻值就用0.1V除以0.35A,约等于0.286欧姆,取标准值0.3欧姆。那么这个电阻上消耗的功率是0.35A的平方乘以0.3欧姆,约等于0.037W,选个0603封装就够用。这里的电流设置逻辑就是欧姆定律,搞清楚基准电压是多少是关键。

实际操作中,FB和CS脚往往配合一个放大电路来用。有些芯片FB脚内部是一个比较器的负输入端,外部的电阻分压网络把输出电压反馈回来,调整开关管的占空比,目的是让输出电压稳定或者输出电流恒定。我调试过一款降压型LED驱动,FB脚外接电阻分压网络,一开始把分压比算错了,输出电压比设计值高了一倍,LED瞬间过流发热。后来用示波器量FB脚的电压波形,发现反馈电压超过了参考电压,才知道是分压电阻阻值配错了。

这里给一个调试思路。调这类芯片,先用万用表量CS脚(或FB脚)的电压,判断它是否接近参考电压;如果偏离太多,优先检查采样电阻阻值和反馈分压电阻比值。不要一上来就去动芯片的外围参数——很多芯片的开关频率、软启动时间由另外一个引脚的外接电容电阻决定,乱调会导致振荡周期异常或者启动冲击电流过大。

另外很多驱动芯片本身也支持PWM调光。方法非常简单:在芯片的PWM调光引脚(有些直接复用EN使能引脚)输入PWM信号,芯片内部的功率管以PWM频率通断,LED电流要么是额定值,要么是零。通过调节占空比来改变平均亮度。这种方式的好处是,芯片始终工作在恒流状态,不会因为调光而产生色偏,LED色温一致性比直接调电流好得多。

2.4 用 PWM 做出动态光效:从呼吸灯到火焰模拟

呼吸灯是PWM调光最经典的入门案例。原理非常简单:占空比从0%逐渐增加到100%,再从100%逐渐减小到0%,循环往复。人眼感觉到的是灯光亮度先缓慢变亮,再缓慢变暗,像人在呼吸一样。这个效果的节奏快慢由占空比变化的步进时间和步长控制。

我在DFRobot的火焰灯模拟方案里看到过一个更进阶的玩法:用若干颗黄色和红色的LED,分别用不同频率、不同占空比的PWM信号驱动,然后让这些信号做随机扰动。比如有一颗LED用20Hz左右的PWM做基础闪烁,另一颗用40Hz的PWM独立闪烁,再把占空比加上随机数扰动,就能模拟出火焰那种不规则跳动的光效。核心就是:动态变化的占空比叠加随机噪声。

这类动态光效实现起来有个要注意的点:如果你用软件延时去改变占空比,占空比的更新频率不能太高也不能太低。太高了,人眼感觉不到变化,觉得灯光在“抖”;太低了,变化又显得突兀,不够柔和。我一般把占空比更新时间控制在10ms到50ms之间,也就是每秒更新20到100次,这样视觉效果最自然。这本质上就是在控制一个“变化的PWM”的时间尺度。

3. 直流电机调速:PWM 的真正硬核战场

3.1 为什么占空比能控制电机转速

LED的PWM调速很好理解,因为人眼会做平均。但电机转速控制就完全不同了——电机可没有“视觉暂留”这种机制。那为什么给电机输出一个PWM方波,就能稳定控制转速?

关键在于电机的电感特性和反电动势。直流电机的绕组是线圈,电感很大,电流不能突变。当你给电机通电的瞬间,电流是缓慢上升的;断电的瞬间,电流也不会立刻跌到零,而是通过续流回路缓慢下降。所以,当PWM频率足够高时,流过电机绕组的电流并不是方波,而是带有一定纹波的近似直流电流。这个平均电流的大小,决定了电机产生的电磁转矩大小,从而决定了转速。

再看电压的角度。电机的转速近似与施加在电枢两端的平均电压成正比。PWM的占空比是50%,那电枢的平均电压就是电源电压的50%,转速大约也是全压转速的50%。这种方式叫“斩波调压”——把连续的电能斩成一段一段,用占空比控制“平均电压”,比串联电阻调压或者线性调压器的效率高得多,因为MOSFET在导通时压降极小,截止时电流为零,功率损耗都很小。

但这里要强调一点:电机不是纯电阻负载,所以“平均电压乘以占空比”这个公式不是精确的转速计算式。电机运转时会产生反电动势(EMF),方向与外加电压相反,实际电流是外加电压减去反电动势后除以绕组电阻。转速越高,反电动势越大,电流越小,这就是电机在空载时转速能快速上升到一个平衡点的原因。PWM调速时,占空比改变的是外加的平均电压,而电机的转速会跟随变化,直到反电动势差不多抵消掉外加电压的一半左右(具体要看负载),系统重新达到平衡。

3.2 驱动电路的关键:MOSFET、续流二极管和死区

直接用单片机IO口驱动电机是不现实的。小电机启动电流几百毫安,大电机几十安培,单片机IO口最多提供几十毫安,强行驱动轻则发热,重则烧毁IO口。所以必须通过功率开关器件来放大驱动能力,最常用的是N沟道MOSFET。

N沟道MOSFET的导通条件是栅源电压(Vgs)超过阈值电压(Vth)。电机驱动的下桥臂MOSFET源极接地,栅极由单片机控制,控制起来比较轻松;但上桥臂MOSFET源极接电机输出端(电压浮动),栅极需要比源极高出一个阈值电压才能导通,这就麻烦了。常见的解决方案是使用专用的栅极驱动芯片,它内部有自举电路,能把栅极电压抬升到比电源电压还高的程度。

这里还要强调续流二极管的作用。电机绕组是感性负载,当PWM关断、MOSFET截止的瞬间,电机电流不能突变,如果没有续流回路,电流会强行流过MOSFET的寄生电容或者直接产生很高的尖峰电压,把管子击穿。正确做法是:在每个电机绕组旁边反向并联一个快恢复二极管(俗称续流二极管),关断瞬间电流通过二极管继续流动,把能量消耗在绕组电阻上,保护MOSFET不受过压冲击。

H桥是直流电机方向控制的经典拓扑,我记得第一次用H桥遇到的问题是上下桥臂直通。如果同一侧的上桥和下桥同时导通,电源直接被短路,瞬间电流极大,管子立刻烧掉。解决方法是:在切换方向时,先让上桥关闭,等待一小段时间(死区时间),再让下桥导通。死区时间通常设为几百纳秒到几微秒,具体取决于MOSFET的关断延迟。STM32的高级定时器在生成互补PWM输出时,可以直接配置死区时间插入,省去了外部的延时处理。

3.3 PWM 模式 1 和模式 2 到底差在哪

在STM32这类ARM单片机上配置PWM时,经常会看到PWM模式1和PWM模式2这两个选项。很多新手在这里一头雾水,不知道选哪个,其实它们的区别就是输出极性相反。

以向上计数模式为例。计数器CNT从0递增到自动重装载值ARR。PWM模式1的规则是:CNT小于比较值CCR时输出有效电平,CNT大于等于CCR时输出无效电平。PWM模式2正好相反:CNT小于CCR时输出无效电平,CNT大于等于CCR时输出有效电平。

那“有效电平”是什么?由另一个配置项决定——输出极性(Polarity)。如果你把输出极性设为高电平有效,那么模式1下,CNT<CCR时引脚输出高电平;如果你设为低电平有效,那么模式1下,CNT<CCR时引脚输出低电平。

给你一个实际例子。用STM32的TIM1_CH1(PA8引脚)输出PWM,配置为PWM模式1,极性设为高电平有效,占空比设为50%。那么PA8引脚上,前半个周期是高电平,后半个周期是低电平。如果你改用模式2,同样参数下,前半个周期变成低电平,后半个周期变成高电平——相当于占空比变成了100%减50%,也就是50%的“互补”信号。

实际应用中怎么选?看你的驱动电路是“高电平驱动”还是“低电平驱动”。如果你的电机驱动芯片使能端是高电平有效(比如EN接高就允许输出),那你应该选PWM模式1加高电平有效,保证占空比越大,高电平时间越长,电机转速越高。如果驱动芯片是低电平有效,或者你想要的是反逻辑控制,那就用模式1加低电平有效,或者模式2加高电平有效。

我遇到过这样一个坑:用TIM1_CH1做电机PWM,配上模式1、高极性,然后又把输出极性配置里的“无效电平”搞反了,结果占空比从0调到100%,电机转速却是先快后慢再快,完全非线性。后来用示波器量PA8的波形才发现,原来我设置的极性让输出的高电平和预期正好相反。用示波器看波形,是排查这类问题最快的方法,别凭感觉猜。

3.4 电机启动的“最低占空比”问题

有一次我做一个小型水泵驱动,用PWM控制转速,占空比从0逐步往上加,结果一直到15%之前电机纹丝不动,过了15%突然猛转起来。原因很简单:电机启动时要克服静摩擦力和自身的转动惯量,如果平均电压太低,产生的电磁转矩不足以让转子转动,电机就“憋”在那里。

而且更要命的是,占空比很低时PWM脉冲宽度很窄,流过电机的平均电流很小,但峰值电流并不小,长时间保持这种状态,绕组可能过热。所以工程上处理电机低速启动的常见做法是:启动瞬间先给一个较大的占空比(比如80%)让电机转起来,然后迅速回落到目标低速占空比,利用电机的惯性维持运转。

如果你需要电机在极低转速下稳定运转,光靠PWM调速是不够的,通常需要配合减速箱降低输出转速,或者用闭环控制(编码器反馈转速)来补偿负载波动。所以做电机控制前先想清楚:你要的是变速范围,还是低速稳定性,这两个目标对硬件的要求差别很大。

4. 单片机产生 PWM 的实操配置

4.1 从定时器到引脚:PWM 信号是怎么生成的

绝大多数MCU的PWM功能都是由定时器(Timer)模块实现的,原理就是一个自由运行的计数器不停计数,和一个预设的比较值做大小比较,然后根据比较结果驱动引脚电平翻转。理解了这个底层逻辑,无论你用什么单片机(STM32、HC32F460、英飞凌CCU6等),配置都是通的。

以STM32F103为例,PWM频率的计算公式很重要,你几乎天天要跟它打交道:

PWM频率 = 定时器时钟频率 / ((预分频系数 + 1) × (自动重装载值 + 1))

举个例子。STM32F103的定时器TIM1挂在APB2总线上,时钟72MHz。如果你设置预分频PSC为71,自动重装载值ARR为999,那么计数器时钟频率 = 72MHz / (71+1) = 1MHz,PWM频率 = 1MHz / (999+1) = 1kHz。占空比则由比较值CCR决定,CCR从0改到999,对应占空比从0%到100%。

这里有个容易搞错的点:预分频系数和自动重装载值都要加1之后再去除,因为硬件寄存器里存的是0到N,实际分频系数是N+1。第一次用STM32CUBMX配置时,我照着教程填了个预分频71,看波形才发现频率不对,就是因为漏了+1的逻辑。

输出引脚的选择也要注意。不是随便一个GPIO都能输出PWM,必须是定时器的通道引脚。比如STM32F103ZET6的TIM1_CH1对应PA8,如果你代码里没把PA8复用为TIM1通道,而是当普通GPIO用了,那引脚上永远看不到PWM波形。在CUBMX里就是选择某个引脚,然后把它配置成“TIM1_CH1”这个复用功能。PA8输出PWM这个场景很典型,初次配置时经常有人配完没反应,一查发现引脚复用没设置。

4.2 STM32CubeMX 配置 PWM 的完整思路

现在ST官方推荐用STM32CubeMX做初始化代码生成。我分享一下配置PWM的关键步骤和每个步骤背后的意图。

第一步,在Pinout视图里点击选择PA8引脚,将它设为TIM1_CH1。CUBMX会自动帮你配好GPIO复用模式,这一步不需要手写寄存器。

第二步,在左侧Category里找到TIM1,在Mode里把Channel1设置为PWM Generation CH1。然后进入Parameter Settings,需要设置几个关键参数:Prescaler预分频、Counter Period计数周期(就是ARR)、Pulse脉冲宽度(就是初始CCR值)、Polarity极性。理论上还有PWM模式1和模式2的选项,默认都是Mode1,大部分情况下保持默认就行。

第三步,也是新手最容易跳过的一步:把PWM信号真正使能输出。CUBMX生成的初始化代码里,定时器默认是关闭的。你必须在用户代码里调用HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);,PWM波形才会出现在PA8上。很多人配置了半天,编译下载,发现引脚没波形,90%的原因就是忘了调用这个启动函数。

第四步,动态调节占空比。HAL库提供了宏:__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, new_ccr_value);,把新的CCR值写进去,占空比立即改变。注意CCR的取值必须在0到ARR之间,超出范围的话,波形行为会变得很奇怪(比如占空比被钳制或者完全无效)。我做呼吸灯时就遇到过这个问题,CCR值不小心超过了ARR,LED亮度直接跳到最亮,调试了半天才反应过来。

CUBMX配好之后还有一个隐藏坑:引脚上电默认状态。有些板子的LED接在PA8上,而PA8上电默认是浮空输入,外部电路可能被拉低导致LED微亮。你在初始化用户代码里必须先配置GPIO输出信号,再启动PWM,否则引脚状态会在初始化和外设启动之间丢失。这个细节遇到一次就会记住了。

4.3 频率与分辨率的权衡艺术

前面提过频率和分辨率互相制约的关系,实际项目里怎么选?我给一个参考坐标系。

做LED呼吸灯或者调光,频率1kHz到5kHz足够,分辨率要求高一些,比如要把亮度细分成256级或者4096级。假设选2kHz,72MHz时钟下,计数器周期 = 72MHz / 2kHz = 36000个时钟,也就是ARR可以设为35999,那么占空比分辨率约为1/36000,远超需求。

做电机调速,频率尽量选20kHz左右,超出人耳听觉范围。这时候计数器周期 = 72MHz / 20kHz = 3600个时钟,ARR设为3599,分辨率仍然有3600级,足够平滑调速。如果你的电机用霍尔传感器做速度闭环,PWM频率还要和采样频率协调,别让采样和PWM开关产生拍频干扰。

如果你的应用需要极高的PWM频率(比如一些数字电源应用要500kHz),那普通定时器的位数就不够了,可能要用到定时器的主模式重映射、或者直接用高级定时器的一些特殊模式。这时候就要考虑用更大位数的计时器或者更高时钟频率的MCU。优先级排序应该是:先满足负载的工作需求,再考虑分辨率够不够,最后才反过来调整定时器参数。

5. PWM 应用中的常见问题与排查实战

5.1 电机抖动、异响和失控

问题一:电机低速时一顿一顿地转,甚至有明显的“咔咔”声。这个大概率是PWM频率太低。我做过实验,30Hz的PWM驱动电机,你能看到电机每秒钟抖动30次,几乎无法稳定控制。解决方案是把PWM频率提高到15kHz以上,电机的电流纹波被电感平滑掉,运转就非常顺畅了。

问题二:电机高速运行时发出高频啸叫。这个声音可能来自PWM频率本身,如果PWM频率落在2kHz到5kHz之间,恰好在人耳最敏感的频率范围,听着会特别难受。对策是直接改频率到20kHz或更高。另外还要排查驱动芯片的内部振荡频率,有些电源芯片的工作频率也在人耳范围附近,会产生同样的异响。

问题三:占空比加到某一档位时,电机突然速度跳变或者失控。优先怀疑电源问题——可能是PWM的开关冲击导致电源电压跌落,控制电路(单片机)瞬间复位。用示波器探头点电机电源两端,能看到巨大的纹波尖峰。处理办法:在电机电源端加大容量电解电容和陶瓷电容,并保证控制电路和功率电路的地线分开走,单点汇接。我调试一次48V电机驱动板时,就因为地线压降导致PWM信号失真,输出波形上叠加了大量毛刺,后来把功率地和信号地在电源输入端单点连接,问题就消失了。

问题四:电机反电动势把单片机打死。大功率电机的电刷换向会产生高压尖峰,通过地线或者信号线耦合回控制电路,导致单片机复位甚至烧毁IO口。解决办法是:控制信号和功率线用光耦或者数字隔离器隔开,PWM信号走隔离通道,电机那边再单独加TVS管吸收瞬态高压。这不是小题大做,我修过好几个人为损坏的板子,都是因为这一步偷懒了。

5.2 LED 闪烁、频闪和拍照水波纹

LED调光时出现人眼可见的闪烁,一定是PWM频率太低或者占空比更新频率太低。这个好解决,频率往上提就行。麻烦的是另一种情况:人眼看起来不闪,但用手机摄像头一拍,屏幕上出现一条条滚动的暗纹。

这是典型的“频闪”问题。手机摄像头的采样帧率和LED的PWM频率之间存在频率差,两者相互作用在画面里产生了摩尔纹效应。比如LED的PWM频率是1kHz,手机快门斩波频率与其不同步,画面就会被拍出亮暗条纹。现在很多装修场景验收灯光就是用手机录像检测频闪,亮暗条纹越明显,频闪越严重。解决方法就是把PWM频率大幅提高,一般做到5kHz以上,频闪现象基本就看不出来了。

另一个LED方面的坑是PWM调光和恒流驱动芯片的配合。有些恒流驱动芯片,PWM调光引脚输入频率太高(超过芯片规格),芯片内部的响应就跟不上了,亮度会出现非线性,甚至芯片自己会抖动。所以LED调光要根据驱动芯片的规格书选择PWM频率,不能一刀切。

5.3 PWM 故障保护与安全设计

在电机驱动这样的功率应用中,PWM输出必须要有故障保护机制。STM32的高级定时器TIM1/TIM8自带刹车(Break)功能:一旦刹车信号有效(比如外部急停按键按下,或者过流信号触发),定时器的PWM输出被强制拉到无效电平,而且这个过程是硬件完成的,不需要CPU干预,响应速度微秒级。

这个设计思路很重要。你想一下,如果电机堵转导致电流飙升,单片机能及时检测到过流信号,但CPU正在执行其他任务,轮询到故障信号可能已经过去了几毫秒——对功率管来说,这几毫秒足够把它烧成灰了。硬件刹车相当于给PWM输出加了一道防火墙,只要有外部故障触发,硬件立刻切断PWM,不等CPU反应。

实际项目里,我习惯把电机驱动芯片的过流保护输出(FAULT引脚)直接接到MCU的刹车输入引脚上。比如用TIM1_BKIN引脚,配置为高电平触发刹车,过流时FAULT变为高电平,PWM立即停止输出。这样即使单片机代码写得再烂、任务调度再慢,功率管也不会因为过流而损坏。

5.4 温度监控、风扇调速与硬盘散热

热词里有一个“PWM怎么监控硬盘的温度”,这个问题背后的实际需求是:怎么根据温度自动调节风扇转速,而风扇调速就是用PWM实现的。

常见的做法是:温度传感器(比如NTC热敏电阻或数字温度传感器DS18B20)采集温度,单片机读取之后查表映射成PWM占空比,占空比控制风扇转速。温度低时占空比给个30%,风扇低速静音运行;温度升高,逐步提高占空比到100%,风扇全速运转。这就是一个简单的开环温控逻辑。

风扇本身分为两线、三线和四线制。四线制风扇里就有一根PWM控制线,输入一个25kHz左右的PWM信号即可调节转速。这也是为什么你会看到“PWM怎么监控硬盘温度”这种搜索词——其实就是用PWM风扇配合软件测温,实现智能调速。热敏电阻的采样精度不要求太高,关键是把温度区间和占空比的映射曲线做好,避免风扇转速在某个温度点上下反复跳变,引起明显的噪音变化。

5.5 一个真实的 PWM 调试速查表

最后我把平时调PWM问题时用的自查清单整理成一张表,省得每次从零开始查。

现象可能原因排查方法解决建议
LED不亮或亮度异常引脚复用没配好、PWM未启动示波器量引脚波形检查GPIO复用配置,调用HAL_TIM_PWM_Start
LED闪烁/拍照水波纹PWM频率过低手机录像观察,示波器测频率提高到5kHz以上
电机一顿一顿转PWM频率太低听声音,看电流波形提高到15kHz~25kHz
电机啸叫但转速正常PWM频率落在听觉范围用耳朵粗略判断改到20kHz以上
电机不转但电流很大占空比太低,启动转矩不足逐步加大占空比观察先用80%占空比启动再回落
MOS管发热严重开关频率过高或驱动不足测温,查看栅极波形降低频率,检查栅极驱动能力
上/下桥臂直通烧管死区时间不够用示波器看互补波形配置死区时间,或外部加延时
PWM输出上有大量毛刺地线布局不当,开关噪声耦合示波器测地线压差功率地和信号地分开布线,单点汇接
过流烧管而程序没反应缺少硬件刹车保护查刹车输入配置将FAULT信号接到BKIN引脚

做电子这行,PWM属于那种“看起来很简单、用起来全是细节”的东西。我刚开始工作那会儿,觉得PWM不就是翻转高低电平吗,后来做电源和电机驱动项目,被频率、死区、续流、刹车这些概念轮番教育过,才真正把这四个字母背后的分量理解透。如果你现在正在做LED调光或者电机调速的项目,建议别只盯着代码跑通,多拿示波器看看真实的波形,多用手摸摸功率管的温度。把波形看明白了,温度摸清楚了,PWM这门手艺,你就已经掌握了大半。

RELATED READING

延伸阅读

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