一.写在前面
在第二话的时候已经简单的对数码管进行了显示测试 51-microcontroler-第二话-数码管 ,但是对于多位显示使用Protues进行多位数码管显示模拟仿真时,总是不能每一位同时显示。
由于本人强迫症(虽然这只是模拟的问题,在实际的物理硬件上实现时看上去是同时显示的),所以必须模拟也得出类似的效果。
那么怎么才能同时显示呢?第一想到的就是锁存器!八位锁存器74HC573,have a try?
二.实现
1.74HC573
真值表如下:
由此表可知:OE直接接GND即可,当需要锁存时就将LE置高电平,D口数据进入,然后置LE为低电平将数据锁住。
2.电路图
第一次操作时忘了P0口没有上拉电阻导致锁存器无法正常工作,排查了很长时间才发现!!!
3.代码
/* Main.c file generated by New Project wizard
*
* Created: 周四 6月 20 2019
* Processor: 80C51
* Compiler: Keil for 8051
*/
#include <reg51.h>
#include <stdio.h>
typedef unsigned char uint8_t;
sbit SEGLock3 = P2^0;
sbit SEGLock2 = P2^1;
sbit SEGLock1 = P2^2;
sbit SEGLock0 = P2^3;
// 0~9 数字字模
const uint8_t n[10] = {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x2, 0x78, 0x0, 0x10};
void showNum(int nums){
uint8_t num[4];
uint8_t i;
for(i = 0; i <=3; i++)
{
num[i] = nums % 10;
nums /= 10;
}
SEGLock3 = 1;
P0 = n[num[3]];
SEGLock3 = 0;
SEGLock2 = 1;
P0 = n[num[2]];
SEGLock2 = 0;
SEGLock1 = 1;
P0 = n[num[1]];
SEGLock1 = 0;
SEGLock0 = 1;
P0 = n[num[0]];
SEGLock0 = 0;
}
void main(void)
{
// Write your code here
showNum(2019);
while (1){
;
}
}
这样操作的好处是单片机不需要一直扫描数码管就可以显示多位数据,可以腾出时间来处理其他事情。坏处是增加芯片,成本增加。
三.扩展
秒表?
/* Main.c file generated by New Project wizard
*
* Created: 周四 6月 20 2019
* Processor: 80C51
* Compiler: Keil for 8051
*/
#include <reg51.h>
#include <stdio.h>
typedef unsigned char uint8_t;
sbit SEGLock3 = P2^0;
sbit SEGLock2 = P2^1;
sbit SEGLock1 = P2^2;
sbit SEGLock0 = P2^3;
int cnt = 0;
int sec = 0;
// 0~9 数字字模
const uint8_t n[10] = {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x2, 0x78, 0x0, 0x10};
void showNum(int nums){
uint8_t num[4];
uint8_t i;
for(i = 0; i <=3; i++)
{
num[i] = nums % 10;
nums /= 10;
}
SEGLock3 = 1;
P0 = n[num[3]];
SEGLock3 = 0;
SEGLock2 = 1;
P0 = n[num[2]];
SEGLock2 = 0;
SEGLock1 = 1;
P0 = n[num[1]];
SEGLock1 = 0;
SEGLock0 = 1;
P0 = n[num[0]];
SEGLock0 = 0;
}
void sleep(int i){
for(; i>0; i--);
}
void main(void)
{
//Write your code here
showNum(sec);
TMOD = 0x01;
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
TR0 = 1;
while (1){
if(TF0 == 1){
TF0 = 0;
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
cnt++;
}
if(cnt == 20){//记满一秒
sec++;
showNum(sec);
cnt = 0;
}
}
}
总结:有的时候由于不仔细导致的小错误会产生一些奇怪的现象,这时我们就需要使用DEBUG进行调试!