文章下方附学习资源 请自主领取
1. 条条大路通罗马
通过前面的学习(传送门),我们了解了PWM的基本概念和产生原理,还学会了用51单片机的定时器产生1kHz的PWM以及用PWM控制LED的亮度。可惜的是产生的1kHz PWM实际上只有139Hz,误差太大了。还好,LED开关频率(PWM频率)在50Hz以上,人眼就察觉不到闪烁了(看到的不一定是真实的)。
那么,用51单片机的定时器能不能产生频率更精确的PWM信 呢?答案是肯定的。
仔细观察如图1所示的PWM波形,可以发现t1和t2相互转换时,输出波形翻转,且周期T=t1+t2。
图1 PWM波形解密
对占空比和频率固定的PWM来说,t1和t2时间是固定的。那么好了,固定的时间都可以用定时器来实现。
于是,我们应该可以用一个定时器来产生PWM,具体思路如下:
(1)设置PWM输出一个初始电平(如高电平)。
(2)用定时器定时时间t1,启动定时器。
(3)t1定时到,触发定时器中断。在定时器中断函数里,做两件事情:
a. 翻转PWM输出;
b. 设置定时器定时时间t2。
(4)t2定时到,触发定时器中断。在定时器中断函数里,做两件事情:
a. 翻转PWM输出;
b. 设置定时器定时时间t1。
(5)重复(3)~(4)。
为了理清思路,画出流程图草图如图2所示,为下一步的编程做准备。
图2 PWM产生流程图
那么问题来了,在定时器中断函数里怎么判断下次定时时间是t1还是t2呢?这就需要引入记忆功能了。你想到什么办法吗?
嵌入式物联 需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!
无偿分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十。
点击这里找小助理0元领取:嵌入式物联 学习资料(头条)
2. 走自己的路
根据流程图设计的代码如下。
#include<reg51.h>//按键和led接口定义sbit key = P3^2;sbit pwm_out = P1^0; //LEDbit timer_stage = 0; //0:高电平输出状态;1:低电平输出状态unsigned int code timer0_X[2][2] ={(65536-600)%256,(65536-600)/256,(65536-400)%256,(65536-400)/256};void timer0_init(); //T0定时器初始化声明void main(){ EA =1; EX0 = 1; //外部中断0打开 IT0 = 1; //外部中断下降沿触发(按键按下触发) PX0 = 1; //外部中断0优先级更高 timer0_init(); pwm_out = 1; //正脉宽 while(1);}//T0定时器初始化函数实现void timer0_init(){ TMOD = 0x01; //定时器方式2 TL0 = timer0_X[0][0]; //PWM脉宽对应的定时器初值 TH0 = timer0_X[0][1]; EA = 1 ; //总中断打开 ET0 = 1; //T0中断打开 TR0 = 1; //启动T0 pwm_out = 1; //PWM初始电平为高电平}//T0中断函数void isr_timer0() interrupt 1{ pwm_out=~pwm_out; //取反 timer_stage =~timer_stage; if(timer_stage == 0) //t1输出 { TL0 = timer0_X[0][0]; //对应的定时器初值 TH0 = timer0_X[0][1]; } else { TL0 = timer0_X[1][0]; //t2对应的定时器初值 TH0 = timer0_X[1][1]; }}
有了上次经验,我们先在Proteus里仿真。PWM的理想频率为1kHz,占空比为60%。仿真结果如图3所示。
图3 定时器产生PWM波形仿真
输出的PWM波形很完美,理论1kHz PWM频率为962Hz,大大超过了我们的预期。
下载程序到开发板运行,用示波器观测到的波形如图4所示。
图4 PWM示波器实测
PWM频率实测为882Hz,占空比为59.61%。占空比误差不大,频率误差为118Hz。
且慢,开发板晶振为11.0592MHz,计数1000次产生的PWM周期和频率计算公式如下:
因此,PWM频率误差实际为Δf=(921-882)Hz=39Hz。
谁吃掉了我们的PWM频率?是定时器的中断函数里的代码吗?还是不知名的巫婆?还是前阵子的 红黑洞?
3. 烧脑
(1)初值赋值对输出PWM有何影响。
仔细分析源代码,你可能会发现定时器初值怎么放在一个预先定义好的二维数组里:
unsigned int code timer0_X[2][2] ={(65536-600)%256,(65536-600)/256, (65536-400)%256,(65536-400)/256};
为了便于理解,用一个示意图画出二维数组的结构,如图5所示。图5 定时器初值二维数组示意图试一试:
有答案了吗?以上两行内容仅供参考。
(2)修改程序,增加一个按键动态改变PWM的占空比。
高能提示:请不要试图在定时器中断函数里用(65536-X)%256计算初值。如果这么做了,请观察PWM频率的变化。
(3)完善程序,实现PWM呼吸灯。
原文链接:
https://mp.weixin.qq.com/s/spaMgknWYRZ3CzkBiaqIWA
?
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!