2、PWM信号生成原理:定时器与比较器的工作原理、PWM波形的产生过程、PWM分辨率与精度
好,咱们进入正题。PWM 信号到底是怎么变出来的?
很多人刚接触 PWM 时,觉得它就是“一会儿高、一会儿低”的方波。没错,表象是这样。但真正要理解它的生成原理,你得钻进芯片内部,看看定时器和比较器这对“黄金搭档”是怎么配合的。
我个人习惯把 PWM 生成比作一个“自动倒计时闹钟”。闹钟响了,你就翻转一次电平。闹钟的计时长度,决定了高电平持续多久。就这么简单。
2.1 定时器:PWM 的“心跳”
定时器是 PWM 生成的基石。没有它,一切都无从谈起。
说白了,定时器就是一个不停向上(或向下)计数的寄存器。它从 0 开始,每个时钟周期加 1,一直加到我们设定的最大值(ARR,Auto-Reload Register),然后归零,重新开始。这个循环周期,就是 PWM 的周期。
核心参数:
- 计数时钟(CK_CNT): 定时器的工作节拍,通常由系统时钟分频得到。
- 自动重装载值(ARR): 决定计数周期,也就是 PWM 的周期。
- 计数模式: 向上计数、向下计数、中央对齐计数。最常用的是向上计数。
举个例子。假设定时器时钟是 72 MHz,我们设置 ARR = 999。那么计数器从 0 跑到 999,需要 1000 个时钟周期。PWM 的周期就是 1000 / 72 MHz ≈ 13.89 μs,频率约为 72 kHz。
一个小技巧: 我习惯先确定目标 PWM 频率,再反推 ARR 和预分频系数。比如我要一个 1 kHz 的 PWM,系统时钟 72 MHz,我会先设预分频为 72-1(得到 1 MHz 的计数时钟),然后 ARR 设为 1000-1。这样频率就刚好是 1 kHz。反过来算,心里更有底。
2.2 比较器:决定“什么时候翻转”
定时器只负责“跑圈”,但什么时候输出高电平、什么时候输出低电平,这事得由比较器说了算。
比较器有两个输入:一个是定时器的当前计数值(CNT),另一个是我们设定的比较值(CCR,Capture/Compare Register)。比较器会不停地比较这两个值。
- 当 CNT < CCR 时,输出高电平。
- 当 CNT >= CCR 时,输出低电平。
你想想看,如果 CCR 设得大,高电平的时间就长,占空比就大。反之亦然。这就是 PWM 占空比调节的本质。
我曾经踩过的坑: 有些芯片的比较器输出极性是可以配置的。默认是“CNT < CCR 时输出高”,但也可以配置成“CNT < CCR 时输出低”。如果你发现 PWM 波形反了,别急着怀疑硬件,先检查一下比较器的输出极性寄存器。我当年调一个电机驱动,波形死活不对,折腾了两天,最后发现是极性配置反了。嗯,这种低级错误,犯一次就记住了。
2.3 PWM 波形的产生过程:一个完整的周期
好了,我们把定时器和比较器组合起来,看看一个完整的 PWM 周期是怎么走的。
- 计数器清零: 定时器从 0 开始向上计数。
- 比较阶段: 计数器 CNT 从 0 增加到 CCR 的过程中,比较器输出高电平。
- 翻转点: 当 CNT 达到 CCR 时,比较器翻转,输出变为低电平。
- 保持阶段: 计数器继续增加,从 CCR 到 ARR,输出保持低电平。
- 周期结束: 计数器达到 ARR,产生溢出事件,计数器归零,输出重新变为高电平。下一个周期开始。
下面这张图可以帮你直观理解这个过程:
从图上可以看得很清楚:三角波是计数器的值,红线是设定的比较值。三角波低于红线时,输出高电平;高于红线时,输出低电平。改变红线的位置,高电平的宽度就变了。
2.4 PWM 分辨率与精度
这两个概念经常被混为一谈,但其实是两码事。我简单给你拆开讲。
2.4.1 分辨率
分辨率指的是占空比可以调节的“步长”。说白了,就是你能把占空比细分到多细。
分辨率由 ARR 决定。如果 ARR = 999,那么计数器有 1000 个离散值(0~999),占空比就可以在 0% 到 100% 之间分成 1000 份。分辨率就是 1/1000 ≈ 0.1%。
计算公式:
分辨率 = 1 / (ARR + 1) × 100%
例如:ARR = 1999,分辨率 = 1/2000 = 0.05%
分辨率越高,PWM 输出就越精细。比如控制 LED 亮度时,低分辨率会导致亮度变化出现明显的“跳变”,看起来一闪一闪的。高分辨率则可以实现平滑的呼吸效果。
2.4.2 精度
精度是另一回事。它指的是实际输出占空比与目标占空比之间的误差。精度受很多因素影响:
- 时钟源精度: 晶振的温漂、时钟分频的误差。
- 定时器计数器的量化误差: 计数器只能取整数值,无法表示小数。
- 比较器的响应延迟: 从 CNT 达到 CCR 到输出实际翻转,存在纳秒级的延迟。
举个例子。你设定占空比为 50%,ARR = 999,CCR = 500。理论上高电平应该持续 500 个时钟周期。但如果时钟有 1% 的误差,实际高电平时间可能是 495 或 505 个周期。这就是精度问题。
我的经验: 在大多数通用 MCU 中,PWM 的精度主要受限于时钟源。如果你需要高精度 PWM(比如用于伺服电机控制),建议使用外部有源晶振,而不是内部 RC 振荡器。内部 RC 振荡器的精度通常在 ±1% ~ ±3% 之间,而外部晶振可以做到 ±50 ppm 甚至更高。另外,有些高端 MCU 提供了“高精度定时器”(HRTIM),它的比较器延迟可以做到皮秒级,精度非常高。
2.5 分辨率与频率的权衡
这里有个很现实的问题:分辨率和频率是矛盾的。
你想想看,定时器的计数时钟是固定的。如果你想要高分辨率,就得把 ARR 设得很大。但 ARR 大了,计数周期就长了,PWM 频率就低了。
| 场景 | 目标频率 | ARR 值 | 分辨率 | 说明 |
|---|---|---|---|---|
| LED 调光 | 1 kHz | 999 | 0.1% | 人眼对低频不敏感,分辨率够用 |
| 电机控制 | 20 kHz | 49 | 2% | 频率高避免噪音,但分辨率低 |
| 音频 DAC | 44.1 kHz | 22 | 4.3% | 需要外部滤波,分辨率不足 |
从表格可以看出,频率越高,ARR 越小,分辨率就越低。这是一个硬约束,没办法同时做到“高频”和“高分辨率”。
避坑指南: 我曾经在一个电机驱动项目里,为了追求高 PWM 频率(想降低电机噪音),把 ARR 设得很小。结果电机在低速时抖动得非常厉害,因为分辨率太低,占空比调节不够精细。后来我不得不降低频率,用更高的分辨率来换取低速时的平稳性。所以,设计时一定要根据应用场景做权衡,不要盲目追求高频。
2.6 小结
好了,这一章的内容就这些。总结一下:
- 定时器提供“时间基准”,ARR 决定 PWM 周期。
- 比较器决定“翻转时刻”,CCR 决定占空比。
- 分辨率由 ARR 决定,精度由时钟和硬件决定。
- 分辨率和频率是矛盾的,需要根据应用做取舍。