YM

Back

STM32 单片机运行时生成任意频率和占空比 PWMBlur image

本文介绍一种算法,可以在运行时接受指定的频率和占空比参数,在单片机上快速计算出 STM32 定时器对应的 PWM 配置,以达到目标参数的配置。利用它可以让 STM32 单片机简单输出低精度的指定方波,不需要额外的波形发生器芯片。

剧透一下,是穷举法,但对于 16 位定时器只需要计算 2162^{16} 次即可求出结果,远小于全部参数穷举的 2322^{32} 次计算,不到 1 秒即可算出结果。

STM32 生成 PWM 的频率和占空比主要由以下图片中红框里面的参数决定:

定时器参数设置

  • 频率由 Prescaler 和 Counter Period 决定
  • 占空比由 Counter Period 和 Pulse 决定,且 Counter Period 越大,占空比的控制越精细
  • 只修改红框里面的参数,其它不修改以保持程序的简单

所以就是:

  • 输入 PWM 的目标频率和占空比
  • 在单片机上快速计算出上面 3 个配置参数,使用这 3 个参数的定时器可以生成最接近目标频率和占空比的 PWM

计算#

我们只要知道 Counter Period 和目标占空比,就可以算出 Pulse 了,所以 Pulse 算搞定了。

然后剩下两个未知数 CPCP (Counter Period) 和 PscPsc (Prescaler)。定时器时钟源频率 FF 以及目标频率 ff 与它们的关系是:

f=F/(CP+1)/(Psc+1)f=F/(CP+1)/(Psc+1)

转一下,可以得到 CP+1CP+1Psc+1Psc+1 的比例:

CP+1PSC+1=Ff\frac{CP+1}{PSC+1}=\frac{F}{f}

其实就是一条线,由于寄存器的位数是有上限的,可以通过穷举的方式计算出所有可能的组合,而且我们已经有了两个参数的比例,根据其中一个参数的值可以直接算出另一个参数,对于 16 位定时器,只需要遍历 65536 次,即可算出最准确频率和占空比对应的 CPCPPscPsc,这个次数对于现在的单片机来说,计算时间不到一秒钟。

在这里我们就遍历 CPCP,然后计算出 PSCPSC 和 Pulse。

实操#

不多废话了,上 C 代码(HAL 库):

主要计算过程在 SetupConfig 函数里面,注释基本都标的很清楚了,而且暴力求解的算法也是比较简单的。

以上代码,只需要修改文件开头的宏定义和几个常量,以及 App 函数里面的 timerBaseFreq,就可以粘贴到任何一个使用 HAL 库的 STM32 工程里面直接使用。也可以粘贴结构体定义和 SetupConfig 函数,直接在现有项目里面使用。

使用下面的配置运行起来看看效果吧!

  • 单片机: STM32F411CEU6
  • 定时器时钟频率: 100MHz

指定:

  • 目标频率: 10kHz
  • 目标占空比: 0.25

程序计算(用时 208ms):

  • Prescaler: 0
  • Period: 9998
  • Pulse: 7499
  • ActualFreq: 10001.000000
  • ActualDuty: 0.250025
  • FreqError: 0.010000%
  • DutyError: 0.010002%

输出波形

拜托,真的很准好吗!

然后再指定一下其它参数都试试看!

Frequency (Hz)Duty Cycle (%)FreqErrorWeightDutyErrorWeightHCLK (Hz)Execution Time (ms)PrescalerPeriodPulseActual Frequency (Hz)Actual Duty Cycle (%)FreqError (%)DutyError (%)
0.150.01.01.0100000000238624991599980000.150.00.00.0
1.050.01.01.01000000002416249915998001.050.00.00.0
100.050.01.01.010000000024162499158100.050.00.00.0
100000.050.01.01.010000000020249911100000.050.00.00.0
1000000.050.01.01.010000000020249111000000.050.00.00.0
10000000.050.01.01.010000000020141110000000.050.00.00.0
123456.050.01.01.010000000020240411123456.78906250.00.0006390.0
1000.01.01.01.0100000000242149950494511000.9809571.0010.0980960.098096
987654.045.6781.01.0100000000203010155980392.187546.0784-0.7352590.876643

看起来效果还是不错的!只要不是频率特别高或者占空比指定的小数位特别多,都是比较准确的。目标频率越低,占空比越容易达标。

STM32 单片机运行时生成任意频率和占空比 PWM
https://yanming.link/blog/generate-any-frequency-and-duty-cycle-pwm-on-stm32-at-runtime
Author YM
Published at November 8, 2024