PWM 生成:用占空比怎么调灯光亮度、电机转速和电源电压
更新时间:2026-09-24。本文是「集成电路大类 · 芯片设计」入门层(beginner) 数字逻辑基础的一篇。数字引脚只能输出 0 或满幅电压,却要调灯光亮度、电机转速、电源输出——靠的就是 PWM(Pulse Width Modulation,脉冲宽度调制):快速通断,用高电平所占比例编码「平均值」。它本质是计数器加数值比较器的简单组合,却是控制世界里出场率最高的数字外设之一。单片机里的定时器/PWM 模块、FPGA 里的 PWM IP、电源管理芯片里的控制环路,骨架都是这一篇要拆的东西。
本文要回答的问题
- 只有 0/1 的数字输出,凭什么能表示「亮度 30%」「转速一半」?
- PWM 的频率、占空比、分辨率三者什么关系,怎么用计数器加比较器生成?
- 边沿对齐和中心对齐 PWM 有何区别,后者为什么对电机和电源更友好?
- 频率选太低或太高各有什么问题?什么是死区时间、互补 PWM、故障刹车?
- PWM 怎么变成真正的模拟电压(DAC)?舵机的「角度脉冲」也是 PWM 吗?
一、占空比:高电平占周期的比例
一个 PWM 信号是一列周期固定的方波。周期 T 内高电平持续 Ton、低电平持续 Toff,T = Ton + Toff。占空比 D = Ton / T,取值 0~100%。D=0 是一直关断,D=100% 是一直导通,中间任意比例对应「每秒钟里有多大比例的时间是高电平」。
关键在于:只要通断足够快,被驱动的「慢对象」来不及跟随每一次跳变,只响应平均值。LED 的发光有余辉、人眼有视觉暂留;电机绕组是电感,电流不能突变;电容上的电压更不可能瞬间充放。于是它们感受到的等效量就是
Vavg ≈ D · VDD10% 占空比看起来就是暗、转得慢、电压低,90% 就是亮、快、高,而引脚全程输出的仍是边沿干净、幅度满幅的数字方波。这正是 PWM 最聪明的地方:不改变电平的「幅度」,只改变高电平的「时间比例」,数字电路因此也能优雅地控制模拟量,不必动用昂贵的 DAC(数模转换器)。
一个生活类比:燃气灶旋钮其实可以理解成「大火点着、马上关掉」的快速循环——点着的时间比例越高,锅感受到的平均火力越大,而火焰本身永远只有「着」和「灭」两种状态。
还要补一个容易忽略的细节:平均值公式是理想近似,真实信号在平均值之上始终叠加着一层和开关频率同频的纹波(ripple)。频率越高、负载的惯性越强,纹波相对平均值就越小;频率太低或负载太「快」,调光就会闪、电流就会断续。PWM 工程的大半权衡,其实都是在和这层纹波打交道。
二、一个计数器加一个比较器就够了
最经典的 PWM 生成电路只需要两块已经学过的东西:一个自由运行的计数器和一个数值比较器。计数器从 0 数到 PERIOD−1 然后回绕(即二进制分频与时钟使能里的模 N 计数),把计数值 cnt 和一个比较阈值 compare 比较:cnt 小于 compare 时输出高电平,否则输出低电平。下面是一份可以直接综合的 Verilog 实现:
module pwm #(parameter W=8)(
input logic clk, rst_n,
input logic [W-1:0] period, // 周期(计数上限)
input logic [W-1:0] compare, // 占空比阈值:高电平持续的计数
output logic pwm_out
);
logic [W-1:0] cnt;
always_ff @(posedge clk)
if (!rst_n) cnt <= 0;
else if (cnt >= period-1) cnt <= 0;
else cnt <= cnt + 1;
assign pwm_out = (cnt < compare); // 比较器:小于阈值为高
endmodule电路结构和波形关系如下图。计数器在时钟驱动下像爬坡一样线性递增,到顶归零重新爬;比较器在每个时钟节拍问一句「cnt 到 compare 了吗」,答案翻转的那一刻就是 PWM 脉冲的下降沿。
读图时抓住一条主线:compare 这个数字直接变成了高电平的持续时间。软件想改占空比,不用动任何模拟器件,只是往比较寄存器里写一个新数字。
PWM 的三要素也由这张图完全确定:
| 要素 | 由谁决定 | 公式/说明 |
|---|---|---|
| 频率 | 时钟与周期寄存器 | f_pwm = f_clk / period |
| 占空比 | 比较阈值 | D = compare / period |
| 分辨率 | 计数器位宽 W | 最多区分 2^W 档占空比 |
注意频率和分辨率在固定时钟下互相牵制:比如 100MHz 时钟、W=10、period=1024,PWM 频率约 97.7kHz、占空比有约千档;若把频率提高到 1MHz,每个周期只剩 100 个计数,档位立刻变粗。想要分辨率高又想频率高,唯一出路是提高输入时钟——这就是高级定时器往往挂在高频时钟域的原因。
再走一遍数字,把三要素算实。假设系统时钟 50MHz(周期 20ns),计数器位宽 8 位、period 设为 200:PWM 频率是 50MHz/200 = 250kHz,每个 PWM 周期 4μs;想输出 25% 占空比,就写 compare = 50,高电平持续 50×20ns = 1μs;想输出一半亮度或一半转速,写 compare = 100。分辨率是 8 位,理论上有 256 档,但 period 只用了 200,实际有效档位是 200 档,每一档对应 0.5%。两个极端值也值得验证:compare=0 时 cnt<0 永不成立,输出恒低;compare≥period 时整个周期都是高,输出恒高——占空比的 0 和 100% 都能精确得到,这正是数字方案比模拟电位器可靠的地方。
三、边沿对齐与中心对齐
计数器的跑法不止一种,由此产生两种对齐风格。
边沿对齐(左对齐):计数器只增不减,每个周期从 0 开始,高电平总是贴在周期的左边缘。实现最简单,前面的代码就是边沿对齐。缺点是谐波丰富,所有脉冲的边沿都落在同一侧,在电机相电流里造成固定方向的纹波。
中心对齐(上下计数):计数器增到顶点再减回来,计数值画出来是三角波;比较匹配在上升段和下降段各发生一次,PWM 脉冲关于周期中心左右对称。它的谐波更干净,更重要的是两相、三相 PWM 可以严格以同一中心对齐,不会出现相间的时序错位,因此是电机 FOC(磁场定向控制)和开关电源同步整流的首选;代价是控制逻辑略复杂,同样周期寄存器下等效开关频率的感受也不同。
| 边沿对齐(左对齐) | 中心对齐(三角计数) | |
|---|---|---|
| 计数器跑法 | 0→顶回绕,锯齿波 | 0→顶→0,三角波 |
| 脉冲位置 | 全部靠左 | 关于周期中心对称 |
| 谐波 | 丰富,纹波方向固定 | 更干净 |
| 多相 PWM | 对齐困难 | 天然严格对齐 |
| 典型场景 | 调光、普通调速 | 电机 FOC、同步整流电源 |
| 实现复杂度 | 最简单 | 略复杂 |
中心对齐还有一个工程上极其实用的好处:脉冲居中后,周期的两个端点(计数器到顶和回零的时刻)恰好是所有桥臂都不切换的安静时刻。电机控制需要在每个 PWM 周期采样相电流做闭环,如果恰好在开关瞬间采样,电流上叠加着开关毛刺,采到的数字基本不可用;中心对齐时让 ADC 在计数器顶点自动触发采样,采到的就是干净的平均电流。边沿对齐则找不到这样一个对所有相都安静的时刻,只能靠软件延时错开边沿,各相采样时刻不一致又会引入新的误差。很多高级定时器把「比较事件触发 ADC」做成硬件直连,就是为了把这条时序链做准。
四、互补 PWM、死区时间与频率选择
驱动电机三相桥或同步整流电源时,一个桥臂有上、下两个开关管,必须用互补 PWM 驱动:上管导通时下管关断,反之亦然。但真实管子的关断比开通慢,如果一路还没关尽另一路就已经打开,输入电源会经过两个管子直通到地,瞬间大电流足以炸管。解决办法是在两路切换之间插入一小段上下都关断的间隔,叫死区时间(dead time),典型几百纳秒,由硬件自动插入、不占软件开销。死区也不是越长越好:死区内电流靠体二极管续流,损耗和压降都更大,所以工程上按管子开关速度选「刚好够」的值。
频率选择则是在两个门槛之间找平衡:
- 下限来自被驱动对象的「慢」得不够。LED 调光要高于约 100~200Hz,否则人眼能看到闪烁,手机摄像头拍还会出现滚动条纹;电机和电源的频率要高到电感电流连续,若落在人耳听觉范围内(约 20Hz~20kHz),电感和磁件会发出吱吱的可闻噪声,所以这类应用普遍取 20kHz 以上;
- 上限来自器件与分辨率。频率越高,开关管每秒钟开通关断的次数越多,开关损耗随次数线性上升,发热加重;栅极驱动器的驱动能力、死区占整个周期的比例也都在限制上限;同时频率升高使每周期计数变少,占空比档位变粗。
常见数字可以有个直观印象:LED 调光几百 Hz 到几 kHz;风扇、电调几 kHz 到 20~30kHz;DC-DC 开关电源几百 kHz 到几 MHz。
死区的量级也可以粗算:假设开关管关断需要 200ns、开通只需 60ns,那么死区至少要覆盖「先给关断信号、确认关尽、再给开通信号」的时间差,工程上取约 300~500ns。在 20kHz PWM 下,500ns 只占周期的 1%,影响很小;但若频率提到 500kHz,同样 500ns 就占了周期的 25%,极端情况下小占空比的脉冲会被死区整个「吃掉」,输出失常。这也是高分辨率电源要选开关速度更快(因而更贵)的管子的原因——省下来的其实是死区损失。
五、影子寄存器与故障刹车
两个硬件机制决定了 PWM 外设能不能用于严肃的功率场合。
影子(预装载)寄存器:如果软件在周期中途改写 compare,当前这个脉冲会立刻被拉长或截短,产生一个宽窄异常的毛刺脉冲,在电机上表现为扭矩抖动,在电源上表现为输出尖峰。硬件 PWM 外设的做法是把新值先写进影子寄存器缓存,等计数器回到 0(边沿对齐)或到达顶点(中心对齐)时才统一载入,保证每个脉冲都完整、干净。配置定时器时看到的「preload / shadow enable」位,开的就是这个功能。
故障刹车(fault / BKIN,break input):过流、过温、欠压等故障信号接到专门的硬件脚,一旦有效,绕过软件、异步地立刻把输出强制到预先设定的安全电平(通常是关断所有桥臂)。从故障发生到输出关断可以在几十纳秒内完成,这是任何中断响应都做不到的——中断要等当前指令执行完、再经过几级流水线和软件判断,动辄微秒到数十微秒,对直通短路来说已经太晚。等软件查询到故障状态时,管子已经安全了。刹车电平、是否过滤毛刺、是否锁定(需要软件显式清除才能恢复输出)通常都可以配置。对电机驱动和电源来说,故障刹车不是加分项,而是安全底线。
六、PWM 当 DAC、舵机与三大应用
PWM 加低通就是简易 DAC:既然 Vavg ≈ D·VDD,用一级 RC 或 LC 低通滤波器把开关纹波滤掉,引脚上剩下的就是随占空比连续变化的模拟电压。滤波器的截止频率要远低于 PWM 频率、又要高于想输出的信号变化速度:产生直流参考电压时可以滤得很狠(大电容、截止频率几 Hz 都行),做音频输出时信号本身有 20kHz 带宽,PWM 频率就得做到几百 kHz 以上,才能在滤掉开关纹波的同时保住音乐细节。D 类功放、数字电位器、产生参考电压都用这一招;滤波不够干净时听到的嘶嘶底噪,就是没滤净的开关频率。它的代价也明确:模拟带宽和开关纹波永远在抢滤波器这一个自由度,真正的高保真场合还是要用专用 DAC。
舵机调的不是平均电压而是脉冲宽度:航模舵机约定周期 20ms(50Hz),用每周期内 0.5~2.5ms 的高电平脉宽编码 0~180° 转角,1.5ms 对应中点。它本质上也是 PWM 信号,但接收方测量的是 Ton 的绝对时长,所以叫它「角度脉冲」更贴切。这也解释了两个常见现象:舵机只认脉宽,剩下 17.5ms 输出是高是低它并不关心,所以一路硬件 PWM 只需配好周期和 compare;而连续旋转舵机把同样的脉宽信号解读成「目标转速与方向」,1.5ms 是停转,脉宽偏离中点越多转得越快——接线完全一样,语义由固件决定。
同一个占空比旋钮,拧在三种负载上就是三大主战场:
这张图回答了开篇的问题:PWM 信号本身不区分用途,是负载的物理特性决定了占空比被翻译成亮度、转速还是电压。调光靠人眼和余辉,调速靠电感的电流惯性,稳压则靠反馈环路根据输出误差自动调节 compare——软件甚至不用知道当前占空比是多少。
这一篇在知识体系里的位置
本篇属于芯片设计入门层的数字控制基础,回答「0/1 的数字信号怎么控制连续变化的物理量」。向前读,PWM 的两块基石分别是计数器与移位寄存器、数值比较器与奇偶校验,时钟回绕原理见二进制分频与时钟使能;横向配套,显示侧可衔接数码管动态扫描,控制量在写进 compare 前往往要经过饱和限幅;向后读,功率侧衔接低功耗与电源管理入门,引脚为什么能驱动外部负载见管脚、驱动能力与 PAD,再往后就是 FPGA/MCU 的高级定时器、电机 FOC 和开关电源控制环路专题。
总结
一句话总结:PWM 用快速通断中高电平所占的比例(占空比 D)编码平均值 Vavg ≈ D·VDD,让只有 0/1 的数字输出也能调灯光、转速和电压;最小实现就是一个模 period 回绕的自由计数器加一个「cnt < compare」比较器——频率由 f_clk/period 决定、占空比由 compare/period 决定、分辨率由计数器位宽决定,后两者在固定时钟下相互牵制;边沿对齐最简单,中心对齐(三角计数)谐波干净、利于多相严格对齐,是电机 FOC 与同步整流电源的首选,而互补上下桥之间必须插死区时间防直通;频率要高过闪烁、可闻噪声和电流纹波的门槛,又受开关损耗和分辨率限制,影子寄存器保证占空比只在周期边界更新、故障脚能异步关断输出;PWM 加低通即简易 DAC,舵机则是在 20ms 周期内用 0.5~2.5ms 的脉宽编码角度——调光、电机、开关电源,是同一个占空比旋钮拧出的三大主战场。