什么是 PWM
PWM(Pulse Width Modulation,脉宽调制)的核心思想很简单:在一个固定周期的方波中,高电平占多长时间是可调的。
占空比 = 有效电平时间 / 周期时间 × 100%
这里的"有效电平"取决于电路设计:
- 有些电路是高电平有效(高电平时 LED 亮)
- 有些电路是低电平有效(低电平时 LED 亮)。CubeMX 中配置
Polarity = Low,代码中用宏TIM_OCPOLARITY_LOW
通过调节占空比,PWM 可以实现:
- LED 调光:高速闪烁,人眼看到的是平均亮度
- 电机调速:平均电压决定转速
- 音频生成:不同频率产生不同音调
PWM 模式
这里先明确几个缩写:
- ARR(Auto-Reload Register):自动重装载寄存器,决定计数上限,也就是 PWM 周期
- CCR(Capture/Compare Register):捕获/比较寄存器,决定电平翻转点,也就是占空比
- CNT(Counter):当前计数值,每个时钟周期递增
定时器有两种 PWM 输出模式:
| 模式 | CNT < CCR 时 | CNT ≥ CCR 时 |
|---|---|---|
| PWM 模式 1 | 输出有效电平 | 输出无效电平 |
| PWM 模式 2 | 输出无效电平 | 输出有效电平 |
最常用的是 PWM 模式 1。
举例(ARR=999,CCR=300,有效电平=低电平):
PWM 模式 1:
- CNT < 300(0~299):输出低电平(LED 亮)
- CNT ≥ 300(300~999):输出高电平(LED 灭)
- → 占空比 30%,LED 亮度约 30%
PWM 模式 2(反向):
- CNT < 300:输出高电平(LED 灭)
- CNT ≥ 300:输出低电平(LED 亮)
- → 占空比 70%,LED 亮度约 70%
简单总结:CNT 的计数范围是 0 ~ ARR;CCR 决定占空比——PWM 模式 1 下 CNT < CCR 输出有效电平,PWM 模式 2 下 CNT ≥ CCR 输出有效电平。两种模式互为反向。
输出通道
一个定时器有多个独立通道,可以同时输出多路 PWM。比如 TIM2 有 CH1~CH4,TIM1 还额外支持互补输出(CH1N 等)。
同一个定时器的所有通道共享 CNT、ARR、PSC,但每个通道有独立的 CCR,可以设置不同的占空比。此外每个通道都有自己的配置寄存器,极性和 PWM 模式也可以单独设置。
参数计算
频率公式:
PWM频率 = Fclk / (PSC + 1) / (ARR + 1)
Fclk是定时器时钟源频率PSC分频后得到计数器的触发频率ARR决定一个周期的计数长度- PWM 频率就是单位时间内完成的周期数
占空比公式:
占空比 = CCR / (ARR + 1) × 100%
代码实践
代码部分其实非常简单,重点是理解前面的原理:PWM 是怎么产生的、ARR/CCR 的关系等。
初始化
CubeMX 配置 PSC、ARR、极性等参数后,自动生成的代码会通过 HAL_TIM_PWM_ConfigChannel 完成初始化。
启动 PWM
CubeMX 只管初始化,不启动输出,必须手动调用:
| |
设置占空比
通过修改 CCR 值来动态调节占空比:
| |
注:如果设置了
CCR > ARR,硬件不会报错,实际效果是占空比被钳位到 100%(整个周期都是有效电平)。逻辑上这通常不是期望行为,注意控制 CCR 的取值范围。