第二次任务
1.如何控制单个数码管
通过引脚P2_4,P2_3,P2_2,进行位选,即选择哪一个数码管进行显示(一次只能控制一个数码管进行显示)若我们想控制第三个数码管进行显示
则先将3减一后转化为三位二进制数010,再取反为101,然后P2_4取1,P2_3取0,P2_2取1.
然后进行段选,即选择一个数码管的哪一个灯进行选择。如果我们想第三个数码管显示3,那么查看电路图,需要a,b,c,d,g对应引脚的小灯进行显示,然后将这些引脚记为1,其他引脚(包括dp端口)记为0,得到11110010,再倒着写,写成01001111,转化为16进制数0x4f,然后P0取0x4f
主函数内容如下
whlie(1)
{
P2_4=1;
P2_3=0;
P2_2=0;
P0=0x4f;
}
即可对一个数码管进行控制。
而在实际应用中,通常用函数实现位选,用数组实现段选
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
void Nixie(unsigned char Location,Number)
{
switch(Location)
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number];
}
这样,前面提到的主函数内容就可以简化为
whlie(1)
{
Nixie(3,3);
}
以下均省略该数组和该函数。
2.如何控制多个数码管
1.多个数码管依次显示
这里先定义一个延时函数,单位为ms
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--){
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
然后若想实现第一,第二,第三数码管依次显示1,2,3,间隔为0.1s,则主函数内容为
while(1)
{
Nixie(1,1);
Delay(100);
Nixie(2,2);
Delay(100);
Nixie(3,3);
Delay(100);
}
2.多个数码管“同时”显示
虽然单片机同时只能控制一个数码管,但我们可以使单片机快速依次显示多个数码管,间隔小于肉眼分辨间隔,这样就可以实现多个数码管“同时”显示。
while(1)
{
Nixie(1,1);
Nixie(2,2);
Nixie(3,3);
}
下载上述代码并启动单片机,我们可以发现数码管出现“残影”。理想情况下单片机进行以下流程:
段选->位选->段选->位选->段选->位选
但是单片机运行速度很快,导致进行下一位段选时,下一位位选数据还没到,数码管就只能对上一个位选数据进行显示,从而造成“残影”
故我们要在下一位段选前要清除位选数据,实现消影。在子函数中进行如下修改
void Nixie(unsigned char Location,Number)
{
switch(Location)
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number];
Delay(1);//留一段时间进行显示
P0=0xff;//清除数据
}
3.部分数码管动态显示,部分数码管静态显示
如果我们想让第七个数码管一直显示0,第八个数码管每一秒从0加到9,到9一秒后再归0呢?
如果直接加入自定义的延时函数
unsigned char num = 0;
void main()
{
while(1)
{
if(num==10)
{
num=0;
}
Nixie(7,0);
Nixie(8,num);
Delay(1000);
num++;
}
}
会发现不但第八个数码管显示异常,而且第七个数码管在闪烁,明显不符合预期。
所以我们要换个思路想一想。
我们可以发现,在数码管显示的子函数中,不计程序执行代码的时间,每一次显示一个数码管,就要经历一个Delay(1)
,即要经历1ms。所以我们可以利用这个来进行计时,不仅可以保证部分数码管持续显示,还能进行部分数码管动态显示。
由计算可知,一次While循环要用2ms,1s总共经历500个while。故定义一个变量time
,每经历1个while就记一次时,time
等于500时num再加一。
unsigned char num = 0;
unsigned int time = 0;
void main()
{
while(1)
{
Nixie(7,0);
if(num==10)
{
num=0;
}
Nixie(8,num);
time++;
if(time==500)
{
time=0;
num++;
}
}
}
下载并运行,数码管如我们所想的那些运行。