改变PWM频率与临时停用PWM:
##PWM频率的改变:
今天我在写无源蜂鸣器播放音乐程序的时候,涉及到了改变定时器ARR的问题,PWM频率的改变必须通过改变ARR来实现。但是我看了其他大佬的博客,发现不能仅仅通过调TIM_SetAutoreload这个函数来实现,否则会出现程序死机的问题。解决办法是启用定时器的预加载寄存器
调用以下函数即可
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState)
这个预加载寄存器的作用大致是这样的:
如果调用TIM_SetAutoreload函数来改变定时器ARR的值,那新的值不会立刻写入ARR寄存器,而是先写入预加载寄存器,等待定时器本次周期结束,进入下一次周期之后,才会把新值写入ARR寄存器,然后下一个周期就是新的周期了
整体效果就是一个缓冲的作用
OK以上就是改变PWM频率的注意事项
临时停用PWM:
这也是比较常用的功能,比如我今天的驱动无源蜂鸣器的程序,用PWM来驱动蜂鸣器,但是不能一直让它响吧,达到指定时间就应该停止PWM输出了。因此呢,我们就需要临时停用PWM,其实非常容易实现,只需要调用TIM_SetComparex将占空比改变为0或者大于等于ARR的值即可。即让占空比为100%或者0%
另外,还有一种思路就是调用TIM_ForcedOCxConfig函数强制输出(具体输出高电平还是低电平与PWM极性有关,极性可以通过TIM_OCxPolarityConfig函数实现),但是这种方法不推荐,因为它是直接把PWM杀死了,如果想要再次启动PWM需要重新配置,非常麻烦!
最后,分享一下刚刚写好的PWM驱动无源蜂鸣器的程序
#include "stm32f10x.h" // Device header
#include "IO.h"
#include "Delay.h"
#include "GuiStar_TIM.h"
u16 ARR;
u16 TIME;
u16 i;
u16 Freq;
void Buzzer_Init(void)
{
GuiStar_PWM_Init(TIM2,1,72,100,1);//初始化PWM
TIM_ARRPreloadConfig(TIM2, ENABLE);//设置预加载寄存器
TIM_SetCompare1(TIM2,0);//关闭PWM
}
/**
* @brief 然蜂鸣器响指定的一段时间
* @param Freq 指定声音的频率
* @param time 指定蜂鸣器响的时间(单位是ms)
* @retval 无
*/
void Buzzer_On(uint16_t freq, u16 time)
{
ARR=1000000/freq;//定时器72分频之后为1MHz,再除以PWM频率得到ARR
TIME=time;//把时间参数传递给全局变量TIME
Freq=freq;//把频率参数传递给全局变量Freq
TIM_SetAutoreload(TIM2,ARR);//设定ARR,调用此函数之后,PWM频率就是参数一指定的频率了
TIM_SetCompare1(TIM2,ARR/2);//开启PWM(占空比为50%),调用此函数之后,蜂鸣器就一指定频率发声了
i=0;//这一句与中断函数有一定关系
}
/*进入中断函数的频率:Buzzer_On的第一个参数freq(即PWM频率)
这个中断函数的逻辑是:调用Buzzer_On后i=0;然后每次进入i都自
增1,如果i等于TIME/1000*Freq说明蜂鸣器的指定时间到了,此时
关闭PWM。(至于为什么,大家自己仔细分析一下TIME/1000*Freq
的含义TIM/1000是把毫秒换算为秒,OK我就提示到这里吧!剩下的交给大家了)
*/
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//判断是否触发TIM2中断
{
i++;
if(i==TIME/1000*Freq)
{
TIM_SetCompare1(TIM2,0);//关闭PWM
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
好了,以上就是关于PWM的一些细节问题,如果有做的不够好的地方,欢迎大家及时提出哈,哈哈,共同学习嘛!