STM32·HAL库开发(七)PWM脉宽调制——案例:LED呼吸灯+sg90舵机
STM32开发之PWM脉宽调制:案例1:PWM控制LED实现呼吸灯效果;案例2:PWM驱动sg90舵机旋转指定角度
目录
【PWM简介】
PWM(Pulse Width Modulation)就是对外输出脉宽(占空比)可调的方波信号,简称脉宽调制
信号频率由自动重装寄存器ARR 的值、PSC、Tclk决定,占空比由比较寄存器CCR 的值决定
【F103C8T6 PWM资源】
高级定时器(TIM1):7路
通用定时器(TIM2~TIM4):各4路
【PWM输出模式】
在向上计数时,一旦 CNT < CCRx 时输出为有效电平,否则为无效电平
在向下计数时,一旦 CNT > CCRx 时输出为无效电平,否则为有效电平
小结: PWM模式1,无论是向上还是向下计数,当计数值小于比较值是输出有效电平
在向上计数时,一旦 CNT < CCRx 时输出为无效电平,否则为有效电平
在向下计数时,一旦 CNT > CCRx 时输出为有效电平,否则为无效电平
小结: PWM模式2,无论是向上还是向下计数,当计数值大于比较值是输出有效电平
【PWM周期、频率、占空比】
PWM的周期 就是 定时器的溢出时间
因为周期是完成一个动作所需的时间,此处动作为高电平到高电平,经过的时间恰为Tout

PWM占空比是指高电平时间占整个周期时间的比例,公式= (高电平时间 / 周期时间) × 100%
占空比的具体公式受PWM模式、有效电平极性、计数方向的影响。在PWM模式1、有效电平为高电平、向上计数的条件下,占空比公式如下:
Duty = CCR / (ARR+1)
另外常用的另一个公式是Duty = (ARR-CRR+1) / (ARR+1)
ARR、PSC和Tclk共同决定了PWM的周期
CRRx(捕获/比较寄存器值)决定了输出有效信号的时间
示例:Tclk = 72M 、ARR (自动重装载的值)= 9999、PSC (预分频系数)= 7199
Tpwm = ( (ARR + 1) * (PSC + 1) ) / Tclk = (7200*10000) / 72 000 000 = 1s
【PWM死区设置】
死区时间(Dead Time)用于在互补PWM信号的跳边沿之间强制加入一段延迟,用于确保同一桥臂的上下两个功率管(如MOS管)不会同时导通,从而避免短路。
死区时间一般选用几百ns,计算公式如下:

2.STM32F407的互补PWM输出带死区控制_break and dead time management-CSDN博客
【demo · PWM_LED】
① STM32F103x8B数据手册/STM32F103产品手册

注意:不是所有GPIO都接到了定时器上,因PC13无法使用定时器,本demo采用PB8



Mode:PWM模式1或模式2
Pulse:占空比;对应捕获/比较寄存器2(TIMx_CCR2)中的CCR2[15:0]
auto-reload preload:自动重装载预装载,启用时ARR的修改会延迟到当前计数周期结束后生效(缓冲写入,避免竞争风险),禁用时ARR的值立即生效,可能打断当前计数周期,适用于紧急制动等需要零延时的场景。
Output compare preload:是输出比较寄存器(CCRx) 的缓冲机制,启用时新写入的CCRx值暂存于预装载寄存器,待下次更新事件(UEV)后生效。禁用时CCRx值立即生效
Fast Mode:针对输出比较(OC)功能的加速机制,用于强制立即更新比较寄存器(CCRx)的值,而无需等待定时器更新事件(UEV)
CH Polarity:有效电平;对应捕获/比较使能寄存器(TIMx_CCER)中的CC2P位。定义输出极性
| 模式 | 占空比更新表现 | 响应速度 |
|---|---|---|
| Fast Mode启用 | 可能产生窄脉冲毛刺(若CNT≈CCRx时写入) | 响应最快 |
| Preload禁用 | 占空比在周期结束时跳变,但无毛刺 | 响应适中 |
| Preload启用 | 占空比平滑过渡,无跳变或毛刺 | 响应最慢 |

关键代码:
HAL_TIM_PWM_Start (&htim4,TIM_CHANNEL_3); //开启PWM输出
//定时器X和通道X,实际使用的哪个定时器哪个通道,就用哪个参数
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_3,pwmVal); //设置默认的占空比值
int main(void)
{
/* USER CODE BEGIN 1 */
uint16_t pwmVal = 0; // 调整占空比
uint8_t dir = 1; // 改变方向,1:越来越亮,0:越来越暗
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM4_Init();
HAL_TIM_PWM_Start (&htim4,TIM_CHANNEL_3);
while (1)
{
if(dir)
pwmVal++;
else
pwmVal--;
if(pwmVal > 500)
dir = 0;
if(pwmVal == 0)
dir = 1;
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_3,pwmVal);
HAL_Delay(2);
}
}
int main(void)
{
/* USER CODE BEGIN 1 */
uint16_t pwmVal = 0; // 调整占空比
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM4_Init();
HAL_TIM_PWM_Start (&htim4,TIM_CHANNEL_3);
while (1)
{
while (pwmVal < 500)
{
pwmVal++;
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, pwmVal); //修改比较值,修改占空比
HAL_Delay(1);
}
while (pwmVal)
{
pwmVal--;
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, pwmVal); //修改比较值,修改占空比
HAL_Delay(1);
}
HAL_Delay(200);
}
【demo · PWM_sg90】

频率: PWM波的频率不能太高,大约50Hz,即周期=1/频率=1/50=0.02s,20ms左右
计算公式:
例: 若周期为20ms,则 PSC=7199,ARR=199
计算方法:ARR+1 = 200 设CCRx为X,列比例式:以0度为例,0.5 / 20 = X / 200 , 得X=5
角度表: 角度由占空比控制



考虑到接线方便,本次使用PB9



注意:可以不开中断
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM4_Init();
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4);
while (1)
{
HAL_Delay(1000);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,5);
HAL_Delay(1000);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,10);
HAL_Delay(1000);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,15);
HAL_Delay(1000);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,20);
HAL_Delay(1000);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,25);
}
}
demo现象:舵机逐步旋转0°,45°,90°,135°,180°,0°
参考:STM32 HAL库 STM32CubeMX -- PWM(呼吸灯)_hal pwm_Dir_xr的博客-CSDN博客
【demo·PWM_WS2812B】
WS2812B彩灯 STM32HAL库开发:PWM+DMA(stm32f103c8t6)_ws2812编程实例-CSDN博客
STM32 HAL库 PWM+DMA 驱动WS2812B彩灯(STM32F030F4P6)_stm32 dma pwm-CSDN博客
更多推荐



所有评论(0)