要求
在单片机实训平台上,利用PWM脉宽信号实现独立按键S7对L1指示灯亮度变化的控制。
具体要求:1.PWM脉宽信号的频率有100Hz。
2.系统上电后L1处于熄灭状态。
3.L1有4种亮度模式:完全熄灭、10%的亮度、50%的亮度、90%的亮度
4.按下S7键循环切换4种模式
思路:
1. 用定时器实现脉宽信号的输出
2.用按键实现4种模式的循环,在每种模式里面要改变:程序的工作状态+状态对应的占空比
电路图:
PWM
PWM也称脉冲宽度调制,是利用微处理器的数字输出来对模拟电路进行控制的一种有效的技术。通过改变脉冲列的周期可以调领,改变脉冲的宽度或占空比可以调压,采用适当控制方法即可使电压与协调变化。
其中,占空比指的是高电平在周期里面占的比例。例如,PWM占空比是50%,意味着在整个周期里面高电平占的时间是50%。在应用中,可以通过设置占空比的大小,来调整直流电机的调速、灯光的亮度、声音的大小、舵机的摆臂(摆臂的角度)
代码
PWM脉宽信号的频率是100Hz
首先定时器初始化设置为:65535-100
void InitTimer0()
{
TMOD = 0x01;
TH0 = (65536 - 100)/256; //定义的100us
TL0 = (65536 - 100)%256;
EA = 1;
ET0 = 1;
}
因为题目要求100Hz,相当于周期是10000us,上面设置的是100us,所以当count达到100时,为一个周期。
上电后L1处于熄灭状态
由于上电后是熄灭状态,说明是先产生一个低电平,让灯灭,再产生一个高电平。
void ServiceTimer0() interrupt 1
{
TH0 = (65536 - 100)/256;
TL0 = (65536 - 100)%256;
count++;
if(count <= pwm_duty)
{
L1 = 0;
}
else if(count < 100) //因为题目要求是100HZ,相当于周期是10000us,上面设置的是100us,所以当count达到100时,为一个周期
{
L1 = 1;
}
else if(count == 100)
{
L1 = 0;
count = 0;
}
按键控制L1的4种状态
void ScanKeys()
{
if(S7 == 0)
{
Delay(500);
if(S7 == 0)
{
switch(stat)
{
case 0 : //按下时,状态是0
L1 = 0; //打开灯
TR0 = 1; //开启定时器,产生脉宽信号
pwm_duty = 10; //设置led为10%的亮度
stat = 1; //状态1,灯处于10%亮度状态
break;
case 1 :
pwm_duty = 50;
stat = 2;
break;
case 2:
pwm_duty = 90;
stat = 3;
break;
case 3 :
L1 = 1; //灭灯
TR0 = 0; //关闭定时器
stat = 0;
break;
}
while(S7 == 0);
}
}
}
完整代码
#include"reg52.h"
sbit L1 = P0^0;
sbit S7 = P3^0;
void SelectHC138()
{
P2 = (P2 & 0x1f) | 0x80;
}
unsigned char pwm_duty = 0;
/*=======键盘扫描=======*/
void Delay(unsigned int t)
{
while(t--);
}
unsigned char stat = 0;
void ScanKeys()
{
if(S7 == 0)
{
Delay(500);
if(S7 == 0)
{
switch(stat)
{
case 0 : //按下时,状态是0
L1 = 0; //打开灯
TR0 = 1; //开启定时器,产生脉宽信号
pwm_duty = 10; //设置led为10%的亮度
stat = 1; //状态1,灯处于10%亮度状态
break;
case 1 :
pwm_duty = 50;
stat = 2;
break;
case 2:
pwm_duty = 90;
stat = 3;
break;
case 3 :
L1 = 1; //灭灯
TR0 = 0; //关闭定时器
stat = 0;
break;
}
while(S7 == 0);
}
}
}
/*========定时器=======*/
unsigned char count = 0;
void InitTimer0()
{
TMOD = 0x01;
TH0 = (65536 - 100)/256; //定义的100us
TL0 = (65536 - 100)%256;
EA = 1;
ET0 = 1;
}
void ServiceTimer0() interrupt 1
{
TH0 = (65536 - 100)/256;
TL0 = (65536 - 100)%256;
count++;
if(count == pwm_duty)
{
L1 = 1;
}
/* else if(count < 100) //因为题目要求是100HZ,相当于周期是10000us,上面设置的是100us,所以当count达到100时,为一个周期
{
L1 = 1;
}
*/
else if(count == 100)
{
L1 = 0;
count = 0;
}
}
/*========主函数========*/
void main()
{
SelectHC138();
L1 = 1;
InitTimer0();
while(1)
{
ScanKeys();
}
}