赞
踩
今天我在写无源蜂鸣器播放音乐程序的时候,涉及到了改变定时器ARR的问题,PWM频率的改变必须通过改变ARR来实现。但是我看了其他大佬的博客,发现不能仅仅通过调TIM_SetAutoreload这个函数来实现,否则会出现程序死机的问题。解决办法是启用定时器的预加载寄存器
调用以下函数即可
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState)
这个预加载寄存器的作用大致是这样的:
如果调用TIM_SetAutoreload函数来改变定时器ARR的值,那新的值不会立刻写入ARR寄存器,而是先写入预加载寄存器,等待定时器本次周期结束,进入下一次周期之后,才会把新值写入ARR寄存器,然后下一个周期就是新的周期了
整体效果就是一个缓冲的作用
OK以上就是改变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的一些细节问题,如果有做的不够好的地方,欢迎大家及时提出哈,哈哈,共同学习嘛!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。