要求:
用stc89c51,数码管,锁存器实现秒表功能
实验仿真图:
1.png加入两个锁存器使单片机能够分时进行位选和段选,这样做的目的是为了节省单片机的端口数量。P0口控制位选和段选,实现动态数码管的显示,P2口连接了矩阵键盘,可以进行功能的拓展。
注意,关于锁存器和数码管无法正常工作的问题,在图1中P0口接了8个上拉电阻,原因是P0口内部没有上拉电阻或电阻不够,如果不外接一个上拉电阻,P0口有可能只能输出低电平和悬空状态,无法输出高电平,而实验中所选用的数码管是共阴极的数码管,会导致数码管不能工作,如果有类似问题出现,可尝试接上上拉电阻。
接有锁存器的动态数码管显示:
动态显示原理图.png动态显示电路如图,共8个共阴极数码管,采用两片74LS573进行驱动,74LS573与74LS373都是8D锁存器,只是573引脚排列更易于布线。其引脚功能为:D1-D8为数据输入端;Q1-Q8为数据输出端;LE为数据输入锁存端,LE=1数据输入D锁存器,LE=0数据不能输入D锁存器,即LE下降沿锁存当前输入数据;地址输出允许端,-OE=0输出锁存数据,-OE=1输出高阻。
电路中,U1输出段码a b c d e f g db,控制显示的字形与小数点,U2输出位选码,控制第几个数码管显示。单片机P1.4、P1.5分别连接到U1、U2的LE,P1.3连接U1和U2的-OE。根据硬件电路,动态显示编程时,应:① P1.3=1,U1、U2输出高阻;② P1.4=1,P0口输出段码,P1.4=0,U1锁存输入的段码;③ P1.5=1,P0口输出位选码,P1.5=0,U2锁存输入的位选码;④ P1.3=0,U1、U2同时输出段码和位选码,进行显示,经过一段时间后,再对另一个数码管做同样的操作。
矩阵键盘
矩阵键盘原理图.png程序源代码
#include"reg51.h"
#include"intrins.h"
#define uchar unsigned char
#define uint unsigned int
sbit OE = P1^3;
sbit LE1 = P1^4;
sbit LE2 = P1^5;
data uchar h,m,i,s;
uchar code dis_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code reg[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
void show();
void delay(uint t){
uchar i;
while(t--)
for(i=0;i<200;i++);
}
void main(){
while(1){
TMOD=0x01; // 设置定时器T0为方式1定时
TH0=(65536-50000)/256; // 给T0装入初值
TL0=(65536-50000)%256; // 给T0装入初值
ET0=1; // 允许T0中断
TR0=1;
EA=1;
show();
} //CPU开中断
}
void T0_int(void) interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
i++;
if(i==20) //1s时间
{ i=0;
s++;
}
if(s==60) //1s时间
{ s=0;
m++;
}
if(m==60) //1s时间
{ m=0;
h++;
}
}
void show()
{
uint i;
for(i=0;i<8;i++)
{
OE = 1;
LE2 = 1;
OE = 0;
P0=~reg[i];
LE2 = 0;
OE=1;
LE1 = 1;
OE = 0;
//OE =0;
if(i==2||i==5)
{
P0=0x40;//发送段码
delay(4); //间隔一段时间扫描
}
if(h<10)
{
if(i==7)
{
P0=dis_code[0];//发送段码
delay(4); //间隔一段时间扫描
}
if(i==6)
{
P0=dis_code[h];//发送段码
delay(4); //间隔一段时间扫描
}
}
if(m<10)
{
if(i==4)
{
P0=dis_code[0];//发送段码
delay(4); //间隔一段时间扫描
}
if(i==3)
{
P0=dis_code[m];//发送段码
delay(4); //间隔一段时间扫描
}
}
if(s<10)
{
if(i==1)
{
P0=dis_code[0];//发送段码
delay(4); //间隔一段时间扫描
}
if(i==0)
{
P0=dis_code[s];//发送段码
delay(4); //间隔一段时间扫描
}
}
if(h>=10)
{
if(i==7)
{
P0=dis_code[h/10];//发送段码
delay(4); //间隔一段时间扫描
}
if(i==6)
{
P0=dis_code[h%10];//发送段码
delay(4); //间隔一段时间扫描
}
if(h>=24)h=0;
}
if(m>=10)
{
if(i==4)
{
P0=dis_code[m/10];//发送段码
delay(4); //间隔一段时间扫描
}
if(i==3)
{
P0=dis_code[m%10];//发送段码
delay(4); //间隔一段时间扫描
}
if(m>60)m=1;
}
if(s>=10)
{
if(i==1)
{
P0=dis_code[s/10];//发送段码
delay(4); //间隔一段时间扫描
}
if(i==0)
{
P0=dis_code[s%10];//发送段码
delay(4); //间隔一段时间扫描
}
if(s>60)s=1;
}
// delay(100);
OE=0;
}
}
注意:如果在仿真实验中数码管无法一起点亮,可能是延时需要改进,延时的总数在300-400之间合适,比如本实验的延时函数中是100个数,那么在外层自定义的数就定在4,共延时400个数,延时函数需要根据实验的不同进行调整。
程序相对简易,没有使用算法,主要思想就是将时、分、秒作为全局变量,在定时器中计时,通过单独的显示函数来显示,主函数只进行中断开关和调用显示函数,所以代码相对易懂,需要注意的是,在定时的过程中,当时间到达最大时需要及时归零,比如计时到达60s是要将秒的全局变量归零,另外,想要做闹钟或者定时器的朋友可以沿用本实验电路和代码,矩阵键盘已连接,只需在代码加入矩阵键盘的操作就能实现想要的功能。
网友评论