在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,在右侧的Channel1到Channel4中可以选择不同的输出模式。例如Output Compare CH1表示在CH1处开启输出比较模式,PWM Generater CH1则表示在CH1开启PWM波输出;
例如选择TIM3的通道,并启用CH1、CH2、CH3的PWM输出,可以看到右侧的PA6,PA7,PB0已经分别被启用为TIM3_CH1,TIM3_CH2,TIM3_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_1到TIM_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模式
通过调整高电平的占比,实现用数字信号模拟输出模拟信号。
部分信息可能已经过时





