今天在QQ群上一个初学单片机的人提了一个关于数码管的问题,主要是程序的问题,由于对基础知识掌握不够,花了比较长的时间才解决,现总结一下其中的细节。
电路中8位数码管是由两个74HC573锁存器分别控制位选和段选的。
原程序大致如下(省去了include和sbit定义),目的是要实现第一个数码管显示“1",但是后面有几个数码管也有显示:
程序1
void main()
{WELA=1;//1P1=0xFE;//2WELA=0;//3DULA=1;//4P1=0x06;//5DULA=0;//6
}
由于程序没有while(1)循环,导致单片机不断循环重新执行程序
执行1时,段选锁存器为0x06,P1为0x06,位选刚打开时,位选锁存器值为0x06,所以六个数码管显示数字“1”
执行2时,位选锁存器值变为0xFE,第一个数码管显示“1”
执行3时,位选值0xFE锁存起来,第一个数码管显示“1”
执行4时,位选锁存器为0xFE,P1为0xFE,段选刚打开时,段选锁存器值为0x06,所以第一个数码管显示如图1形状
执行5时,段选锁存器值变为0x06,第一个数码管显示“1”
执行6时,段选值0xFE锁存起来,第一个数码管显示“1”
我原本是想让他在程序结尾加一个while(1)空循环,结果加错了,成了这样:
程序2
void main()
{while(1) {WELA=1; //1P1=0xFE; //2WELA=0; //3DULA=1; //4P1=0x06; //5DULA=0; //6}
}
程序2和1效果相近,由于while(1)的原因,切换更快,显示亮度更高
后来有人说中间加一个P1=0xFF,看上去好了一些,后面几个数码管不亮了,实际上第一个数码管显示不正常,还是没有完全解决问题:
程序3
void main()
{DULA=1; //1P1=0x06; //2DULA=0; //3P1=0xFF; //4WELA=1; //5P1=0xFE; //6WELA=0; //7
}
执行1时,位选锁存器为0xFE,P1为0xFE,段选刚打开时,段选锁存器值为0xFF,所以第一个数码管显示如图1形状(时间很短,所以亮度低)
执行2时,段选锁存器值变为0x06,第一个数码管显示“1”
执行3时,段选值0xFE锁存起来,第一个数码管显示“1”
执行4时,P1变为0xFF
执行5时,段选锁存器为0x06,P1为0xFF,位选刚打开时,位选锁存器值为0xFF,所以八个数码管都不显示
执行6时,位选锁存器值变为0xFE,第一个数码管显示“1”
执行7时,位选值0xFE锁存起来,第一个数码管显示“1”
如果按照我原先的理解,结尾处加一个while(1)空循环,最后是可以正常显示的:
程序4
void main()
{WELA=1; //1P1=0xFE; //2WELA=0; //3DULA=1; //4P1=0x06; //5DULA=0; //6while(1); //7
}
执行到3时,位选锁存器为0xFE
执行到6时,段选锁存器为0x06
执行到7时,锁存值不再改变,第一个数码管显示“1”,显示正确
为了使程序更加完善,以下写法更加可靠:
程序5
void main()
{P1=0xFE; //1WELA=1; //2WELA=0; //3P1=0x06; //4DULA=1; //5DULA=0; //6while(1); //7
}
执行2、3时,位选锁存值为0xFE
执行5、6时,段选锁存值为0x06
执行到7时,锁存值不再改变,第一个数码管显示“1”
附注:
573的 LE锁存使能引脚 高电平时输出和输入相同,低电平时 输出不再改变,即下降沿锁存,也就是低电平锁存。