脉冲宽度调制 (PWM) ,是英文" Pulse Width Modulation "的缩写,简称脉宽调制,是利用
微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽
度的控制。
图中,我们假定定时器工作在向上计数 PWM 模式,且当 CNT<CCRx 时,输出 0 ,当 CNT>=CCRx 时输出 1 。那么就可以得到如上的 PWM 示意图:当 CNT 值小于 CCRx 的时候, IO 输出低电平 (0) ,当 CNT 值大于等于 CCRx 的时候,IO 输出高电平 (1) ,当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。 改变 CCRx 的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM 输出的频率,这就是 PWM 输出的原理。(PS:操作寄存器请大家自行查阅手册,我这里还是只演示CubeMX+HAL库函数)。
下面来操作CubeMX输出PWM,首先还是选择外部晶振 和开启总线调试接口;接下来有个关键点,配置挂载tim的时钟总线频率,我这里统一用了72M;
然后是第二个关键点,选择时钟模式,时钟源选择Internal Clock,然后开启对应的通道并选择PWM生成模式。
最后一个配置要点参数设置,首先明确一点,一组高低电平组成的PWM波形的周期计算公式如下:,其中Prescaler是预分频系数,Counter Period是自动重装载寄存器里存储的计数周期,Ftim是挂载TIM的时钟总线上的时钟信号频率。计数模式一般习惯性选择向上计数(Count Mode选择UP),内部时钟预分频不用,影子寄存器可以使能一下。
触发输出参数选择中触发事件选择复位Reset,主从模式选择disable。
最后的PWM生成参数,PWM模式选择模式1,两者的区别是
- PWM mode 1 :
- 在向上计数中,当计数值小于CCR(捕获/比较寄存器)值时,PWM输出高电平;当计数值大于CCR值时,PWM输出低电平。
- 在向下计数中(如果存在中心对齐模式),当计数值小于CCR值时,PWM输出低电平;当计数值大于CCR值时,PWM输出高电平。
- 这种模式下,PWM信号的输出逻辑在低电平和高电平之间切换,以控制PWM的占空比。
- PWM mode 2 :
- 在向上计数中,当计数值小于CCR值时,PWM输出低电平;当计数值大于CCR值时,PWM输出高电平。
- 在向下计数中(如果存在中心对齐模式),当计数值小于CCR值时,PWM输出高电平;当计数值大于CCR值时,PWM输出低电平。
- 与PWM mode 1相反,这种模式下PWM信号的输出逻辑在高电平和低电平之间切换,以控制PWM的占空比。
我们可以先试着用CubeMX配置固定占空比的PWM方波,这种需求只需要一行hal库代码就能实现。主要精力放在填写参数上,首先将预分频系数设置为7199,计数周期为4999,挂载在一个72Mhz的时钟线上,所以理论上一对高低电平组成的周期为0.5s。然后将PWM Generation Channel4中的Pulse设置为2000(理论占空比为2000/5000=0.4),极性设置为低(我的开发板上的LED灯低电平点亮),随后生成代码。
在TIM初始化函数中直接开启PWM。
cpp
/* USER CODE BEGIN TIM3_Init 2 */
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);
/* USER CODE END TIM3_Init 2 */
观察示波器波形,可以看到高低电平周期为500ms,其中300ms输出高电平,200ms输出低电平,和理论值相符合。LED灯只是不停地闪烁,并没有实现呼吸灯效果。
当然更多时候占空比需要可调,我来演示一下pluse占空比选择0,输出比较预装载寄存器需要使能,快速模式可以关闭,极性选择高。
生成代码至IDE开始调参。
①命名一个占空比变量
cpp
/* USER CODE BEGIN 1 */
uint16_t pwm=0; //调控占空比
/* USER CODE END 1 */
②主循环里写逻辑功能
cpp
/* USER CODE BEGIN 3 */
while(pwm<499)
{
pwm++;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_4, pwm); //通过修改比较值来改变占空比
}
while(pwm)
{
pwm--;
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_4, pwm); //通过修改比较值来改变占空比
HAL_Delay(1);
}
HAL_Delay(200);
}
/* USER CODE END 3 */
观察示波器波形论证结果
宏观来讲,每个循环最后延时200ms已经实现。
每个高低电平组成的周期实测500us,理论值(71+1)*(499+1)/72000000=0.0005s基本符合。
占空比大致为80%,输出400us低电平之后输出100us高电平,也符合理论范围。占空比调制成功实现了呼吸灯效果。