基于STC89C52单片机的霓虹灯
1、设计要求
? ? ? ??使用PWM驱动8个LED灯
????????人眼不能观察到灯光全灭
????????灯光要有动画效果
2、设计概述
? ? ? ? 本实验所用芯片为STC89C52,所用硬件是由华清远见基于STC89C52开发的智能小车,该小车具有流水灯模块、蜂鸣器模块、独立键盘模块、矩阵键盘模块等。这里着重介绍流水灯模块,流水灯模块共有八个不同颜色的LED灯,由主控芯片STC89C52的P1端口八个引脚分别控制。此外,STC89C52不具备PWM的硬件模块,所以需要自己写程序模拟PWM方波,PWM就是脉冲宽度调制的缩写,方波高电平时间跟周期的比例叫占空比,例如1s钟内高电平占0.5s,占空比就是50%。
3、原理图以及线路连接
? ? ? ? 本实验只需要用到智能小车的核心板,不需要连接线。下图为流水灯模块的原理图
4、要求分析和参考代码
? ? ? ? 首先是第一、二条要求?:使用PWM驱动8个LED灯
????????????????????????????????????????????????人眼不能观察到灯光全灭
? ? ? ? 由于没有PWM的硬件模块,要用软件实现PWM的话首先就得用到定时器,所以先把定时器要用到的功能设置好。下面是参考代码,首先先把led灯全部灭掉,然后是设置定时器,这里用到的是STC89C52的定时器0,因为方式2的定时是最精准的,在这里也够用,所以设置定时器0的工作方式为方式2;然后就是初值的设置,这里我们设置的周期为100us,也就是每100us进入一次中断,由方式2的初值计算公式 256 - X = 100 解得初值X为156;然后就是将定时器0的中断允许位以及总中断的中断允许位置1,开启总中断以及定时器0中断,最后TR0置1,开启定时器。
void neon()
{
P1 = 0xFF; //初始将led灯全部灭掉
TMOD = 0x02; //定时器0设置方式2
TH0 = 156; //设置进入中断函数的周期
TL0 = 156;
EA = 1; //总中断以及定时器0中断允许位置1
ET0 = 1;
TR0 = 1; //开启定时器0
}
? ? ? ? 定时器功能设置好之后就是中断函数了,同样对照参考代码,逐条解释
? ? ? ? 这里time就是一个无符号变量,每进入一次中断函数就+1,当time==99时,我们就将P1口全部置0,也就是开启LED灯,当time等于100时,我们将P1口全部置1,也就是关闭LED灯,同时将time清0,这样就能实现循环,每进入100次中断,就是一个周期,由于定时器设置的进入中断时间是100us,进入100次的时间也就是100us × 100 = 10ms,由于时间是极短的,人眼不能察觉到它的变化,这样我们就实现使用PWM驱动8个LED灯以及人眼不能观察到灯光全灭的要求。
void inter_timer0(void) interrupt 1
{
time++;
if(99 == time) //这里值越大,灯光越暗
P1 = 0;
if(100 == time)
{
P1 = 0xff;
time = 0;
}
}
最后的要求就是?灯光要有动画效果
? ? ? ? 首先,要有动画效果的话,八个灯的亮度就不能是一致的,不然就看不到灯光的变化,这里,就只要把上面代码中的?P1 = 0xff?改为?P1 = 0xfe ,这样,在P1口置1的时候,P1.0口就不会置1,led0也就不会灭,而其他的led1~led7都会灭掉,这样就静态的显示了一盏灯亮,其他灯相对较暗的效果,但这样还是静态的,要有动画效果,就要让相对较亮的这盏灯不断地移动,要达到这个效果,就只要动态的改变P1口的值就行了,这里设置一个变量t,对应P1口的值,然后动态改变t的值,同时设置一个变量i,表示较亮的灯在当前位置停留的时间。当停留时间足够,即i==10,以后,首先将i清0,然后将i左移,由原先的0000 0001变为0000 0010,然后取反,变成1111 1101,这样较亮的灯,就从led0,变成了led1,然后不断左移,当t==0x80,也就是
1000 0000之后,将t重新置1,不断循环,这样就达到了动态的效果。。
void inter_timer0(void) interrupt 1
{
time++;
if(99 == time) //这里值越大,灯光越暗
P1 = 0;
//P1 = ~t;
if(100 == time)
{ //P1 = 0;
P1 = ~t;
time = 0;
i++;
if(10 == i) //通过改变这个值的大小可以改变灯变化的速度
{
i = 0;
if(t < 0x80)
t = (t << 1);
else if(t == 0x80)
t = 1;
}
}
}
?
|