在上一讲代码基础上,根据常识,变量没有到达10时,数码管1和数码管2应该是不需要点亮的,也就是高位不显示0。
笔者参考了宋老师的代码,他的做法就是额外开辟出一个数组用来做缓存,P0去取这个数组里的值即可,初始化的时候如下
unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
然后各块内存用来存放对应的数码管显示的状态值,比如像上一讲的代码,我们这样存放好:
LedBuff[0]= LedChar[Second%10];
LedBuff[1]= LedChar[(Second/10)%10];
LedBuff[2]= LedChar[(Second/100)%10];
到时赋给P0的值就是LedBuff[0],LedBuff[1],LedBuff[2]。像一开始LedBuff[1]和LedBuff[2]的值都是0xFF, Second没到10时,
不执行“LedBuff[1]= LedChar[(Second/10)%10]; ”,即使数码管1已在允许被点亮状态,
但是由于“P0= LedBuff[1];(也就是P0= 0xFF;)”导致所有段的灯都无法点亮也就不显示内容了。
当然用额外的数组存放数码管状态值还有另一个好处,当我们学到后面的计分功能要这样显示时
中间要显示非数字或字母时,给LedBuff[2]和LedBuff[3]提前赋值0xBF只点亮一段灯就在中间显示一杠了。
现在我们实现上一讲的功能但高位不显示0。
#include <reg52.h> sbit ADDR2 = P1^2; sbit ADDR1 = P1^1; sbit ADDR0 = P1^0; sbit ENLED = P1^4; sbit ADDR3 = P1^3; unsigned char code LedChar[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};//数码管状态值初始化 unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};//数码管显示缓存区 void main() { unsigned int i=0,x; unsigned char Second=0;//定义一个一秒之后自增1的变量 ADDR3 = 1;//使能三八译码器 ENLED = 0;// while(1) { LedBuff[0]=LedChar[Second%10]; if(Second>=10)LedBuff[1]= LedChar[(Second/10)%10]; //Second没到达10之前不更新LedBuff[1]的初始值 if(Second>=100)LedBuff[2]= LedChar[(Second/100)%10];//Second没到达100之前不更新LedBuff[2]的初始值 if(Second==0){ LedBuff[1]=0xFF;LedBuff[2]=0XFF; } //Second到达255之后再加1就溢出变为0了,这时候要再次熄灭这两个数码管 for(x=0;x<32765;x++)//循环持续一定的时间 { P0=0xFF;//端口状态全部熄灭数码管里的LED达到刷新作用 switch(i) { case 0: ADDR2 = 0;ADDR1 = 0;ADDR0 = 0;P0=LedBuff[0];i++;break; case 1: ADDR2 = 0;ADDR1 = 0;ADDR0 = 1;P0=LedBuff[1];i++;break; case 2: ADDR2 = 0;ADDR1 = 1;ADDR0 = 0;P0=LedBuff[2];i=0;break; } } Second++;//持续一定的时间之后变量自加1 } }
笔者在修改for循环的x值时,软件调试发现无法使Second准确地间隔1秒后自加,这里大家不用太纠结Second能否均匀的1秒后自加1,而是学会了本节想表达的知识点,后面我们也不会用到for循环来实现让三八译码器间隔导通不同的三极管了,到时学会定时器知识内容即可完美实现这方面的功能,笔者也是考虑到大家刚入门需要多点基础的例程代码来熟悉单片机编程,所以才不会跨度太大地教大家新知识。
本文固定URL:https://www.dotcpp.com/course/196