mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1514 字
4 分钟
STM32-09:TIM定时器-PWM模式
2026-07-25

在PWM方波中,通过调整高电平的占比,并以更快的速度切换高低电平,可以用数字信号模拟输出模拟信号。


输出比较模式#

在输出比较模式下,原有的捕获寄存器变为比较寄存器,用于输入的GPIO口也变为输出脉冲信号。此模式下,我们需要先向比较寄存器中写入一个数值,然后根据选择模式输出不同的信号:

  • 冻结模式(Frozen):输出通道的GPIO口会无视比较结果,保留旧的输出状态;(何意味)
  • 强制有效(Forced Active):输出通道的GPIO口会无视比较结果,持续输出高电平;(何意味x2)
  • 强制无效(Forced Inactive):输出通道的GPIO口会无视比较结果,持续输出低电平;(何意味x3)
  • 匹配时有效(Active Level on Match):仅当计数器值和比较寄存器值相等时,输出有效电平,但不会自动重设为无效电平;
  • 匹配时无效(Inactive Level on Match):仅当计数器值和比较寄存器值相等时,输出无效电平,但不会自动重设为有效电平;
  • 匹配时翻转(Toggle on Match):仅当计数器值和比较寄存器值相等时,翻转当前的输出电平。

要不直接跳过这段吧


PWM原理#

在PWM方波中,通过调整高电平的占比,并以更快的速度切换高低电平,可以用数字信号模拟输出模拟信号。 例如,PWM波占空比为60%时,由于高低电平的切换非常迅速,在宏观上就可以认为输出了1.98V的电压。
此外,通过调整PWM波的占空比,频率等属性,还可以控制电机的转速,舵机的角度。


PWM模式#

在默认的向上计数模式下:

  • PWM模式1:当计数器值小于比较寄存器的值时,输出有效电平;当计数器的值大于或等于比较寄存器的值时,输出无效电平;
  • PWM模式2:与PWM模式1相反,当计数器值小于比较寄存器的值时,输出有效电平;当计数器的值大于或等于比较寄存器的值时,输出无效电平。

红石比较器
上述的有效电平无效电平,在从比较寄存器发出之后,还会进入输出控制器,默认地,有效电平对应高电平,无效电平对应低电平,我们也可以配置输出控制器使其翻转,使有效电平对应低电平,无效电平对应高电平。相当于加了个非门

TIP

补充: 计数器除了向上计数模式之外,还有向下计数模式中央对齐模式
向下计数模式中,则与向上计数模式相反:

  • PWM模式1:当计数器值大于比较寄存器的值时,输出无效电平;当计数器的值小于或等于比较寄存器的值> 时,输出有效电平;
  • PWM模式2:当计数器值大于比较寄存器的值时,输出有效电平;当计数器的值小于或等于比较寄存器的值> 时,输出无效电平。

中央对齐模式则是前半段向上计数模式,后半段向下计数模式
通常地,这两种模式不常被使用。


芯片配置#

在CubeMX中,左侧Timers点开任意定时器,先勾选Internal Clock,在右侧的Channel1Channel4中可以选择不同的输出模式。例如Output Compare CH1表示在CH1处开启输出比较模式,PWM Generater CH1则表示在CH1开启PWM波输出;
例如选择TIM3的通道,并启用CH1、CH2、CH3的PWM输出,可以看到右侧的PA6PA7PB0已经分别被启用为TIM3_CH1TIM3_CH2TIM3_CH3,我们在这三个GPIO口接入LED灯,即可利用PWM波做出呼吸灯的效果。
在底下的Configuration栏目,可以进行更多的设置。例如此处将Prescaler设置为72-1,将Counter Period设置为100-1,则每秒计数1M次,每秒输出10000个PWM波。继续向下则是PWM的设置:

  • Mode:选择PWM模式1或者PWM模式2;
  • Pulse:比较寄存器初始的值;
  • Output compare preload:比较寄存器的影子寄存器机制,与自动重装载寄存器的影子寄存器机制相同;
  • Fast Mode:高速模式;
  • CH Polarity:极性翻转,即对输出控制器的配置。

代码配置#

先启用CH1、CH2、CH3通道的PWM波输出:

HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);

由上述的原理可知,PWM输出的占空比和比较寄存器息息相关,因此我们只需要修改比较寄存器中的值,即可修改输出PWM波的占空比,进而修改最终小灯的亮度。
用于写入比较寄存器值的宏函数:

__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__);

其中:

  • __HANDLE__:要操作的定时器的句柄,即我们启用的&htim3
  • __CHANNEL__:要操作的通道,从TIM_CHANNEL_1TIM_CHANNEL_4
  • __COMPARE__:设置比较寄存器的值。

在死循环中写入对小灯的控制程序:

while (1)
{
for(int i=0;i<=100;i++){
if(i<=25){
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, -2*i+50);//B
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, -2*i+100);//G
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 2*i+50);//R
}else if((i>25)&&(i<=50)){
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 2*i-50);//B
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, -2*i+100);//G
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, -2*i+150);//R
}else if((i>50)&&(i<=75)){
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 2*i-50);//B
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 2*i-100);//G
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, -2*i+150);//R
}else if((i>75)&&(i<=100)){
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, -2*i+250);//B
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 2*i-100);//G
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 2*i-150);//R
}
HAL_Delay(20);
}
}

烧录程序后,可以看见小灯以一种十分炫酷的方式在闪烁。


总结#

相关函数#

HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel);//启用PWM波输出
__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__);//设置比较寄存器的值

PWM模式#

通过调整高电平的占比,实现用数字信号模拟输出模拟信号。

STM32-09:TIM定时器-PWM模式
https://nf3eb.github.io/posts/stm32/stm32-09/
作者
NF3eb
发布于
2026-07-25
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录