实验原理图如下:
器件:7SEG-MPX2-CC-BLUE两位八段共阴数码管,显示为蓝色。还有红黄绿三个LED灯。
其中,P2口的前七位接数码管的7个段选,P3口的前两位接两个位选,P1口的前三位接三个LED灯。
实验的目的是数码管从10开始减到00,然后下一个小灯亮。这里我们不用精确的1秒计时,而是用语句进行一个延时。
检测器件
首先检测一下所有器件是否能正常运行,先这样写源程序:
#include
#define uchar unsigned char //宏定义,用uchar代替unsigned char
#define uint unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbit wei1 = P3^0; //位定义
sbit wei2 = P3^1;
sbit red = P1^0;
sbit yellow = P1^1;
sbit green = P1^2;
void delay();
void main()
{
red = 0; //点亮LED灯
yellow = 0;
green = 0;
while(1)
{
P2 = table[1]; //让数码管动态显示‘10’
wei1 = 0;
delay();
wei1 = 1;
P2 = table[0];
wei2 = 0;
delay();
wei2 = 1;
}
}
void delay()
{
uint i,j;
for(i=5;i>0;i--)
for(j=1;j>0;j--);
}
运行效果如下:
可以看到所有的器件都能正常运行。下面我们就可以开始一点一点写程序了。
先写倒计时程序。
主函数可改为:
void main()
{
uchar shi,ge; //shi代表第一个数码管显示的字符,ge代表第二个数码管显示的字符
uint time; //用time变量进行延时
shi = 1; //第一个数码管刚开始显示‘1’
ge = 0; //第二个数码管刚开始显示‘0’
time = 5000; //time初始化为5000
red = 0; //刚开始红灯亮
while(1)
{
time--; //time自减
if(time==0) //当time减到0时,说明已经过了大约1秒,数码管应该变化了
{
time = 5000; //time重新赋值,以便再次计时
shi = 0; //第一个数码管显示‘0’
ge = 9; //第二个数码管显示‘9’
}
P2 = table[shi]; //让数码管进行动态显示
wei1 = 0;
delay();
wei1 = 1;
P2 = table[ge];
wei2 = 0;
delay();
wei2 = 1;
}
}
可以看到,我们是用自减语句加if条件判断来实现延时的,因为动态显示要在很短的时间内重复执行那几条语句,所以while(1){}中如果有一个很长时间的延时,那么动态显示的效果就出不来了。
到这里数码管已经能从‘10’变为‘09’了,那怎样才能循环变化呢,我们只需加入几个if判断语句即可。主函数改为如下:
void main()
{
uchar shi,ge;
uint time;
shi = 1;
ge = 0;
time = 5000;
red = 0; //先点亮红灯
while(1)
{
time--;
if(time==0)
{
time = 5000;
if(shi==1) //当第一个数码管为‘1’时,才变化第一个数码管
{
shi = 0;
ge = 9;
}
else ge--; //当第一个数码管不为‘1’时,只让第二个数码管自减
if(ge==0) //当第二个数码管为0时,数码管重新显示‘10’
{
shi = 1;
ge = 0;
}
}
P2 = table[shi];
wei1 = 0;
delay();
wei1 = 1;
P2 = table[ge];
wei2 = 0;
delay();
wei2 = 1;
}
}
这样倒计时程序就写好了。
加入小灯控制语句
倒计时程序写好后,只需要在适当的位置加入小灯控制语句即可。完整的源程序如下:
#include
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbit wei1 = P3^0;
sbit wei2 = P3^1;
sbit red = P1^0;
sbit yellow = P1^1;
sbit green = P1^2;
void delay();
void main()
{
uchar shi,ge,temp; //加入变量temp,它用来记录哪个灯亮着
uint time;
shi = 1;
ge = 0;
temp=0; //开始temp为0,表示红灯亮着
time = 5000;
red = 0; //先点亮红灯
while(1)
{
time--;
if(time==0)
{
time = 5000;
if(shi==1)
{
shi = 0;
ge = 9;
}
else ge--;
if(ge==0)
{
shi = 1;
ge = 0;
temp++; //每过10秒下一个小灯点亮
if(temp==3) //当temp为3时,让它重新变为0
temp = 0;
}
}
switch(temp) //对temp的不同值进行小灯的亮灭设置
{
case 0: green = 1;red = 0;break; //0表示红灯应该亮,将其前面的绿灯关闭。
case 1: red = 1;yellow = 0;break; //1表示黄灯应该亮,将其前面的红灯关闭。
case 2: yellow = 1;green = 0;break; //2表示绿灯应该亮,将其前面的黄灯关闭。
}
P2 = table[shi];
wei1 = 0;
delay();
wei1 = 1;
P2 = table[ge];
wei2 = 0;
delay();
wei2 = 1;
}
}
void delay()
{
uint i,j;
for(i=5;i>0;i--)
for(j=1;j>0;j--);
}
需要说明的是,因为端口位定义的red,yellow,green不能像其他变量一样进行if条件判断,所以我们加入了变量temp,它起的是标志的作用,用来标记哪个灯亮着。这样就能根据它来控制小灯了。标志的用途很多,在一个大程序里可能要用到很多标志,但标志会影响程序的可读性,要慎重使用。
最终效果如下: