第三章:PWM波形反推——从占空比和频率,反推定时器的配置参数

各位好,欢迎来到第三章。

上一章我们聊了怎么从波形里读出频率和占空比。但说实话,那只是第一步。真正有意思的是——你拿到这两个数字之后,怎么反推出芯片里定时器是怎么配的?

这就像你看到一辆车的尾灯亮起频率,反推出司机踩刹车的力度。嗯,有点那个意思。

3.1 核心公式:定时器与PWM的关系

先别急着看代码,咱们把数学关系理清楚。

一个标准的PWM输出,背后站着三个关键参数:

  • 预分频器(PSC):决定定时器时钟跑多快
  • 自动重装值(ARR):决定PWM周期
  • 比较值(CCR):决定占空比

它们之间的关系,说白了就两个公式:

PWM频率 = 定时器时钟频率 / ((PSC + 1) * (ARR + 1))
占空比 = CCR / (ARR + 1)   (向上计数模式)

注意,这里有个 +1 的细节。我见过不少新手在这里翻车。定时器的寄存器是从0开始计数的,所以实际计数值要加1。你想想看,ARR设为99,实际计数是0到99,一共100个时钟周期。

关键点:ARR + 1 才是真正的周期计数值。CCR 是计数值,不是百分比。

3.2 反推第一步:从频率反推(PSC+1)*(ARR+1)

好,假设你从示波器上读到了一个PWM波形:

  • 频率:1kHz
  • 占空比:25%

你的MCU定时器时钟是72MHz。那么第一步,我们算一下总的分频系数:

总系数 = 72MHz / 1kHz = 72000

这个72000就是 (PSC+1) * (ARR+1) 的乘积。

到这里,你可能会问:那PSC和ARR到底怎么分?

嗯,这就是反推的难点所在。同一个乘积,可以有无数种拆分方式。比如:

  • PSC=71, ARR=999 → (72)*(1000)=72000
  • PSC=719, ARR=99 → (720)*(100)=72000
  • PSC=7199, ARR=9 → (7200)*(10)=72000

哪个才是对的?

我的经验:我个人习惯先看占空比的分辨率。占空比25%,如果ARR=9,那CCR只能是2.25?不可能,寄存器不能存小数。所以ARR不能太小。

3.3 反推第二步:从占空比反推CCR和ARR

占空比25%,意味着 CCR / (ARR+1) = 0.25。

也就是 CCR = (ARR+1) * 0.25。

CCR必须是整数。所以 (ARR+1) 必须是4的倍数。

我们回头看刚才那三种拆分:

  • ARR=999 → ARR+1=1000,是4的倍数 → CCR=250 ✅
  • ARR=99 → ARR+1=100,是4的倍数 → CCR=25 ✅
  • ARR=9 → ARR+1=10,不是4的倍数 → CCR=2.5 ❌

所以第三种直接排除。

那前两种怎么选?

实际项目中:我曾经遇到过一个问题——电机控制要求PWM频率1kHz,占空比分辨率要0.1%。ARR=99时,分辨率只有1%,不够用。最后选了ARR=999的方案。

一般来说,ARR越大,占空比调节越精细。但ARR太大,定时器中断频率会降低,实时性受影响。这是个权衡。

3.4 常见定时器模式对反推的影响

刚才我们假设的是向上计数模式。但实际中还有:

  • 向下计数模式:公式一样,但CCR含义略有不同
  • 中央对齐模式:频率公式要除以2,因为一个周期内计数走了两趟

举个例子,中央对齐模式下:

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

如果你用向上计数的公式去套中央对齐的波形,算出来的PSC和ARR会差一倍。我刚开始做STM32的时候就在这栽过跟头。

注意:反推之前,先确认定时器的工作模式。看波形是对称的还是不对称的?对称的波形大概率是中央对齐模式。

3.5 实战案例:一个完整的反推过程

好,咱们来走一遍完整的流程。

已知条件:

  • 定时器时钟:72MHz
  • 波形频率:50Hz
  • 占空比:7.5%
  • 波形不对称(上升沿快,下降沿慢)→ 向上计数模式

第一步:算总系数

总系数 = 72,000,000 / 50 = 1,440,000

第二步:拆分PSC和ARR

占空比7.5% = 3/40。所以ARR+1最好是40的倍数。

我试了几个组合:

PSC ARR ARR+1 CCR 是否合理
1439 999 1000 75 ✅ 常用
7199 199 200 15 ✅ 分辨率低
2879 499 500 37.5 ❌ 非整数

我个人会选择PSC=1439, ARR=999, CCR=75。为什么?因为ARR=999是很多MCU的默认值,而且分辨率够用。

第三步:验证

频率 = 72M / (1440 * 1000) = 50Hz ✅
占空比 = 75 / 1000 = 7.5% ✅

一个小技巧:如果你不确定PSC和ARR的分配,可以看看波形有没有抖动。PSC太大(比如超过65535),定时器时钟太慢,波形容易受噪声影响。我遇到过几次这种情况,后来都尽量让PSC小一些。

3.6 避坑指南

最后,分享几个我踩过的坑:

  • 坑一:忘了 +1。ARR=999时,实际周期是1000。算CCR时用999做分母,结果全错。
  • 坑二:没考虑死区时间。有些PWM波形(比如H桥驱动)会在上升沿和下降沿之间插入死区。这时候占空比看起来会偏小。
  • 坑三:误把脉冲宽度当成占空比。有人看到高电平时间1ms,周期10ms,直接说占空比10%。但如果波形是负逻辑呢?高电平反而是关断信号。

我曾经在一个电机驱动项目里,因为没注意死区时间,反推出来的CCR总是差那么几个数。折腾了两天才发现,原来是硬件自动插入了死区。从那以后,我拿到波形第一件事就是看上升沿和下降沿之间有没有间隙。

好了,这一章的内容就到这里。下一章我们会聊怎么把这些反推出来的参数,写成实际的寄存器配置代码。到时候我会拿STM32和GD32的库函数做例子,手把手教你怎么配。

记住:波形会说话,关键是你得听得懂。