在使用STM32系列微控制器进行PWM输出时,有时会遇到一个令人困惑的问题:即使将PWM的占空比设置为100%(即ARR等于CCR),输出的信号却不是持续的高电平,而是出现了一个小脉冲。这个问题常常让开发者感到困惑,因为理论上,当占空比为100%时,输出应该是稳定的高电平。
问题背景
在使用STM32的定时器进行PWM输出时,我们通常会使用定时器的自动重载功能(Auto-Reload Register,ARR)来设置PWM的周期,使用定时器的比较寄存器(Capture/Compare Register,CCR)来设置PWM的占空比。当我们将占空比设置为100%时,意味着CCR寄存器的值与ARR寄存器的值相等,此时定时器应该输出一个持续的高电平。
问题分析
然而,有时我们会发现,即使将占空比设置为100%,输出的信号却不是持续的高电平,而是出现了一个小脉冲。这是因为STM32定时器在计数器溢出时会产生一个更新事件(Update Event),在这个事件发生时,定时器的输出会被更新。而在PWM模式下,更新事件会导致定时器输出的状态发生变化,即使占空比设置为100%,也会出现一个小脉冲。
PWM从0-100%时产生一个脉冲
解决方法
通过查看参考手册我们发现,当TIMx_ARR与TIMx_CCRx相等时,在最后一个时钟位会产生一个小脉冲,这符合我们遇到的问题,要想PWM的占空比设置为100%时,输出一个持续的高电平,则比较寄存器(CCR)需要大于自动重载功能(ARR)。
通过修改程序,使PWM占空比为100%时,CCR加1,即可输出持续高电平。
// 定时器计数
#define TIM1_PERIOD (100 - 1)
// 设置PWM占空比
User_StatusTypeDef Tim1_PwmPulseSet(uint32_t Channel, uint32_t Pulse)
{
uint32_t tim_ccr;
if (Pulse < 100)
tim_ccr = TIM1_PERIOD * Pulse * 0.01;
else
tim_ccr = (TIM1_PERIOD * Pulse * 0.01) + 1; // 想要占空比为100%时输出高电平,必须使TIMx_CCRx中的比较值大于自动重装载值(TIMx_ARR)
if (Channel == LL_TIM_CHANNEL_CH1)
{
LL_TIM_OC_SetCompareCH1(TIM1, tim_ccr);
}
else if (Channel == LL_TIM_CHANNEL_CH2)
{
LL_TIM_OC_SetCompareCH2(TIM1, tim_ccr);
}
else if (Channel == LL_TIM_CHANNEL_CH3)
{
LL_TIM_OC_SetCompareCH3(TIM1, tim_ccr);
}
else if (Channel == LL_TIM_CHANNEL_CH4)
{
LL_TIM_OC_SetCompareCH4(TIM1, tim_ccr);
}
return STATUS_SUCCESS;
}
程序修改后经过示波器测量如下。
PWM从0-100%持续高电平
总结
在STM32定时器输出PWM时,当占空比设置为100%时,出现小脉冲的问题可能是由于定时器的更新事件导致的。要想PWM的占空比设置为100%时,输出一个持续的高电平,则比较寄存器(CCR)需要大于自动重载功能(ARR)。
在实际开发中,还是得多看参考手册进行设计。正确理解和使用STM32定时器的工作原理对于解决PWM输出时可能出现的问题至关重要。通过深入学习参考手册中关于定时器的章节,可以更好地掌握定时器的各种工作模式、功能和特性。同时,合理设置自动重载寄存器(ARR)和比较寄存器(CCR)的值,以及灵活应用中断处理和定时器的各种功能,可以更有效地解决PWM输出时可能出现的问题,确保输出信号的稳定性和可靠性。因此,在开发过程中,及时查阅参考手册并深入理解其中的内容,对于提高开发效率和解决问题具有重要意义。
参考资料
- STM32F10x参考手册
- STM32F10x用户手册