各位读者朋友们你们好,感谢你们能点开这篇文章,作为一个非硬件专业的学生,我没有扎实的硬件基础,很担心自己所写内容没有理论基础或者存有漏洞,如果有不对的地方,期待您能指正,一起学习。交通红绿灯的设计算是51的小入门。涉及仅有数码管,LED交通灯,Delay函数延时的使用。
总览:一:数码管用来显示数字。
二:LED交通灯本质上就是二极管,含有红绿黄,作为交通灯。
三:Delay函数,用以计时。(在还未学习计时器的情况下,用Delay函数计时,虽有误差,但能接受)
我的板子是清翔的A4板,静态数码管原理图如下:
一个静态数码管其实是由八个小的二极管组成,如上图,你可以看到,如果想让数码管显示数字1,就是点亮b,c两个二极管,其他不点亮。(原理图中每个二极管分别用字母a~Dp代替,下文同上)
我们再设计接线,做过入门的点亮第一个LED灯的都知道,点亮LED就是给电平置低,我设计的接线是引脚P0^0~P0^7接J8的A~Dp。
这样我们就可以写出每个数字所需点亮的二极管以及对应的引脚了:
数字0:a,b,c,d,e,f 对应引脚:P00 P01 P02 P03 P04 P05
数字1: b,c 对应引脚:P01 P02
数字2:a,b,d,e,g 对应引脚: P00 P02 P03 P06
数字3:。。。。。。。
我们写一个函数,将0-10的数字包含进去:
void NiXie(unsigned char Number)
{
switch(Number)
{
case 0:P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=0;break;
case 1:P0_1=P0_2=0;break;
case 2:P0_0=P0_1=P0_3=P0_4=P0_6=0;break;
case 3:P0_0=P0_1=P0_2=P0_3=P0_6=0;break;
case 4:P0_1=P0_2=P0_5=P0_6=0;break;
case 5:P0_0=P0_2=P0_3=P0_5=P0_6=0;break;
case 6:P0_0=P0_2=P0_3=P0_4=P0_5=P0_6=0;break;
case 7:P0_0=P0_1=P0_2=0;break;
case 8:P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=P0_6=0;break;
case 9:P0_0=P0_1=P0_2=P0_3=P0_5=P0_6=0;break;
case 10:P0_6=0;break;
}
}
数字10我用中间那个杠,也就是g编码的二极管代替了(对应P0^6),毕竟这个例程只有一个数码管...
这样利用switch的好处是很明显的,当我们输入一个Number,对应的case就会自动对应这个数,比如Number=5,对应case 5:对应的数码管被点亮,实现显示数字5的效果。
注:数字之间的切换
比如数字1过后想亮数字2,需要把数字1亮过的二极管全部置高后再行动,若没有置高,实际上就是数字之间发生重叠,为统一起见,每亮(显示)一个数字后,将所有引脚置高,全部关灯,即:
P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=P0_6=P0_7=1;//return
(提示:如果你用模块化编程,会使main函数看起来更简洁)
数字显示做好后,我们来看红绿灯:在我这块板子上,红黄绿灯,我接的是:
P2^2------绿灯
P2^3------黄灯
P2^4------红灯
延时函数Delay:如果你看到这篇文章的话,应该还没由接触到吧,Delay函数是可以在生成器中自动生成的,看下图:
系统频率也就是晶振,结合自己的板子,有的是12.0000KHZ的,我的是11.0592KHZ的,定时长度可设计最小为微秒的计时单位,在本实验中毫秒更适用,指令集选择STC-Y1对应STC89C型号的板子,都勾选好后,就可以把生成的代码复制来用了,在主函数中,直接调用这个函数,就可以起到延时的效果了。
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
看此函数,结合我们的需求我们可以稍作改动,1000毫秒为一秒,我们想要1000毫秒来实现交通灯,这里只有1毫秒,我们只需要加个while函数循环我们想要的秒数的次数,就可以实现了
修改的代码如下:
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
while(xms)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
xms--;
}
}
我们写一个参数,自己输入你想延时多少毫秒,比如xms=1000,while循环里每循环一次xms--;就可以实现循环xms次一毫秒的循环了。1000次就是一秒钟了。(我在这里将函数名改为了Delay())
说了这么多,是时候上代码了:
#include
#include
void NiXie(unsigned char Number)
{
switch(Number)
{
case 0:P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=0;break;
case 1:P0_1=P0_2=0;break;
case 2:P0_0=P0_1=P0_3=P0_4=P0_6=0;break;
case 3:P0_0=P0_1=P0_2=P0_3=P0_6=0;break;
case 4:P0_1=P0_2=P0_5=P0_6=0;break;
case 5:P0_0=P0_2=P0_3=P0_5=P0_6=0;break;
case 6:P0_0=P0_2=P0_3=P0_4=P0_5=P0_6=0;break;
case 7:P0_0=P0_1=P0_2=0;break;
case 8:P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=P0_6=0;break;
case 9:P0_0=P0_1=P0_2=P0_3=P0_5=P0_6=0;break;
case 10:P0_6=0;break;
}
}
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
while(xms)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1)
{
unsigned int i=10,j=3,k=10;
for(i;i>0;i--)
{
P2_2=0;//Grenn light
NiXie(i);
Delay(1000);
P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=P0_6=P0_7=1;//return
}
P2_2=1;//off the green light
for(j;j>0;j--)
{
P2_3=0;//Yellow light
NiXie(j);
Delay(500);
P2_3=1;
Delay(500);//实现闪烁
P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=P0_6=P0_7=1;//return
}
P2_3=1;
for(k;k>0;k--)
{
P2_4=0;//Red light
NiXie(k);
Delay(1000);
P0_0=P0_1=P0_2=P0_3=P0_4=P0_5=P0_6=P0_7=1;//return
}
P2_4=1;
}
}
在黄灯部分,我设计黄灯闪烁,更像交通灯了哈哈哈哈。(接下来准备写交通红绿灯设计二,用定时器减小误差,另,一个数码管确实有些可怜了,准备加个LCD1602或者用两个数码管)。
实验现象:
如有不懂的地方,欢迎您的私信。
如有写的不对的地方,非常期待能收到您的指正。