3、PWM软件配置:时钟源选择、预分频器设置、自动重装载值配置、比较值配置

好,咱们进入正题。PWM 的软件配置,说白了就是搞定四个寄存器:时钟源、预分频器、自动重装载值和比较值。这四个东西配合好了,PWM 才能按你的心意输出波形。

我刚开始做 PWM 驱动时,总觉得配置很简单,不就是写几个寄存器嘛。结果有一次,电机转起来嗡嗡响,频率完全不对。查了半天,发现是时钟源选错了,预分频算得也不对。嗯,从那以后,我每次配置都会老老实实把时钟树过一遍。

3.1 时钟源选择

时钟源是 PWM 的“心跳”。没有它,定时器根本跑不起来。不同芯片的时钟源选项不太一样,但大体上分三类:

  • 内部时钟(CK_INT):最常用,直接来自系统时钟或 APB 总线时钟。
  • 外部时钟模式 1(TIx):从外部引脚输入时钟信号,适合需要同步外部事件的场景。
  • 外部时钟模式 2(ETR):通过专门的 ETR 引脚输入,频率可以更高。

我个人习惯,90% 的场景都用内部时钟。简单、可靠,不容易出幺蛾子。只有做特殊同步或编码器应用时,才会考虑外部时钟。

小提示: 选时钟源时,记得查一下芯片的时钟树框图。有些定时器挂在 APB1 上,有些挂在 APB2 上,最大频率不一样。我见过有人把挂在 APB1 上的定时器配到 72MHz,结果死活不工作——因为 APB1 最高只有 36MHz。

3.2 预分频器设置

时钟源选好了,接下来就是预分频器(PSC)。它的作用是把时钟频率降下来,让定时器计数不那么快。

预分频器的值怎么算?公式很简单:

定时器时钟频率 = 时钟源频率 / (PSC + 1)

举个例子,时钟源是 72MHz,你想要定时器跑在 1MHz,那么:

PSC = 72MHz / 1MHz - 1 = 71

注意,预分频器寄存器通常是 16 位的,所以 PSC 的取值范围是 0~65535。如果你算出来的值超过这个范围,就得考虑换时钟源或者调整系统时钟了。

注意: 预分频器的值在定时器使能后修改,不会立即生效。需要等到更新事件(UEV)发生后,新的分频值才会被加载。我曾经踩过这个坑——改了 PSC 以为立刻生效,结果波形还是老样子,折腾了半天才发现要等一个更新事件。

3.3 自动重装载值配置

自动重装载值(ARR)决定了 PWM 的周期。说白了,就是定时器从 0 数到 ARR,然后重新从 0 开始。

PWM 的频率计算公式:

PWM频率 = 定时器时钟频率 / (ARR + 1)

结合前面的预分频,完整的公式就是:

PWM频率 = 时钟源频率 / ((PSC + 1) * (ARR + 1))

举个例子,你想要一个 1kHz 的 PWM,时钟源 72MHz,预分频后定时器时钟为 1MHz:

ARR = 1MHz / 1kHz - 1 = 999

ARR 也是 16 位的,最大 65535。如果你需要更低的频率,可以加大 PSC 或者 ARR。但要注意,ARR 越大,PWM 的分辨率就越高(因为比较值的步进更细)。

经验之谈: 我一般先定 PWM 频率,再反推 PSC 和 ARR。比如做 LED 调光,频率选 1kHz 就够,人眼看不出来闪烁。但做电机控制,频率至少 10kHz 以上,不然电机噪音大得吓人。

3.4 比较值配置

比较值(CCR)是 PWM 的“灵魂”。它决定了占空比——也就是高电平占整个周期的比例。

占空比计算公式:

占空比 = CCR / (ARR + 1) * 100%

比如 ARR = 999,你想要 50% 占空比:

CCR = 999 * 50% = 499.5 → 取整为 499 或 500

注意,CCR 不能大于 ARR,否则输出会一直为高电平(或低电平,取决于极性配置)。

比较值可以在运行时动态修改,实现呼吸灯、电机调速等效果。但要注意修改时机——最好在更新事件发生时修改,避免产生不完整的脉冲。

小技巧: 我写 PWM 驱动时,习惯把 CCR 的更新放在定时器更新中断里。这样能保证每个周期都更新一次,波形非常平滑。如果放在主循环里更新,可能会因为中断优先级问题导致更新不及时,波形出现抖动。

3.5 配置流程总结

说了这么多,咱们把整个配置流程串起来。下面这张图可以帮你理清思路:

PWM 软件配置流程 时钟源选择 预分频器设置 自动重装载值配置 比较值配置 使能 PWM 输出 关键公式 PWM频率 = 时钟源 / ((PSC+1)*(ARR+1)) 占空比 = CCR / (ARR+1) * 100% PSC、ARR、CCR 均为 16 位 注意事项 • 修改 PSC 需等待更新事件 • CCR 不能大于 ARR • 更新 CCR 最好在中断中完成

3.6 完整配置示例

下面是一个完整的 PWM 配置代码示例,以 STM32 为例:

// 目标:输出 1kHz、50% 占空比的 PWM
// 时钟源:72MHz(内部时钟)

// 1. 使能定时器时钟
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;

// 2. 配置预分频器:72MHz / (71+1) = 1MHz
TIM2->PSC = 71;

// 3. 配置自动重装载值:1MHz / (999+1) = 1kHz
TIM2->ARR = 999;

// 4. 配置比较值:50% 占空比
TIM2->CCR1 = 500;

// 5. 配置输出模式:PWM 模式 1,极性高
TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;  // PWM 模式 1
TIM2->CCER |= TIM_CCER_CC1E;  // 使能输出

// 6. 使能定时器
TIM2->CR1 |= TIM_CR1_CEN;
重要提醒: 配置顺序不能乱!一定要先配 PSC 和 ARR,再配 CCR,最后使能输出。如果先使能定时器再配寄存器,可能会产生不完整的第一个脉冲。我吃过这个亏——示波器上看到第一个脉冲宽度不对,查了半天才发现是配置顺序的问题。

3.7 常见问题与避坑

问题 原因 解决方法
PWM 频率不对 时钟源选错或预分频算错 重新计算 PSC 和 ARR,确认时钟树
占空比始终为 0% 或 100% CCR 超出范围或极性配置反了 检查 CCR 是否 ≤ ARR,检查 CCER 极性位
第一个脉冲异常 配置顺序不对 先配寄存器,再使能定时器
修改占空比后波形抖动 CCR 更新时机不对 在更新中断中修改 CCR

嗯,以上就是 PWM 软件配置的核心内容。时钟源、预分频器、自动重装载值、比较值,这四个参数搞明白了,PWM 配置就掌握了八成。剩下的就是根据具体芯片的手册,把寄存器配对就行。