以上是proteus里的原理图。以下是程序:
#include<reg51.h>
sbit ksec=P1^1;
sbit kmin=P1^2;
sbit khour=P1^3;
sbit pkey=P3^2;
unsigned char secshi=0,secge=0,minshi=0,minge=0,hourshi=0,hourge=0;
unsigned int num=0,sec=0,min=0,hour=0;
unsigned char code table[10]={
0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XD8,0X80,0X90
};
void delay(unsigned int);
void keyscan();
void display();
void init(void)
{
TMOD=0x01; //定时器0工作在方式1
TH0=(65536-50000)/256; //定时50ms,定时器0高8位初值
TL0=(65536-50000)%256; //定时50ms,定时器0低8位初值
EA=1;
ET0=1;//开启中断允许寄存器
TR0=1;//使TR0置位,启动定时器,定时器便开始计数 ,计数溢出时,自动进入中断服务程序
//开启外部中断,并使得低电平触发
EX0=1; // ????INT0???
IT0=0; // ????INT0(?????)
}
void main()
{
init();
IE=10000011; //0X8A=10000011,打开外部中断和定时器中断
while(1)
{display();//调用显示函数
keyscan();//键盘扫描程序
}
}
void delay(unsigned int z)
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}//延时函数
//时钟设置子程序,定时器中断程序
void time0() interrupt 1
{num++;//计数加1
TH0=(65536-50000)/256; //重装初值
TL0=(65536-50000)%256;
}
// LED显示程序
void display()
{if(num==20)
{num=0;
sec++;//如果num=20,则一秒时间到,秒加1
if(sec==60)
{sec=0;
min++;//如果sec=60,则一分钟时间到,分加1
if(min==60)
{min=0;
hour++;//如果min=60,则一小时时间到,小时加1
if(hour==24)
{hour=0;
min=0;
sec=0;//到了23点59分59秒时候 {zh1}归零
}
}
}
}
secge=sec%10;//秒求余
secshi=sec/10;//秒求模
minge=min%10;//分求余
minshi=min/10;//分求模
hourge=hour%10;//小时求余
hourshi=hour/10;//小时求模
P0=0x80; //OXFE是什么?位选?选中10000000,{zh1}一位,秒?
P2=table[secge]; //段选
delay(4);
P0=0x40; //01000000,选中秒的第十位
P2=table[secshi];
delay(4);
P0=0x20; //00100000,选中分的个位
P2=table[minge];
delay(4);
P0=0x10; //00010000 ,选中分的十位
P2=table[minshi];
delay(4);
P0=0x08; //00001000,选中小时的个位
P2=table[hourge];
delay(4);
P0=0x04;//00000111 ,选中小时的十位
P2=table[hourshi];
delay(4);
}
// 按键控制子程序,将出去暂停键之外的其他键放在键盘扫描程序里,暂停键放在外部中断0里面,为了保证记住上一个状态
void keyscan()
{if(ksec==0)
{delay(5);
if(ksec==0)
{sec++;
if(sec>=60)
sec=0;
}
while(!ksec);
}
if(kmin==0)
{delay(5);
if(kmin==0)
{min++;
if(min>=60)
min=0;
}
while(!kmin);
}
if(khour==0)
{delay(5);
if(khour==0)
{hour++;
if(hour>=60)
hour=0;
}
while(!khour) ;
/*if(pkey==0)
{delay(5);
if(pkey==0)
{ while(!pkey);
TR0=~TR0;
EA=~EA;
ET0=~ET0;
num=0;
}
while(!pkey);
} */
}
}
void int_1()interrupt 0
{
if(pkey==0)
{delay(5);
if(pkey==0)
{ while(!pkey);
TR0=~TR0; //将定时器0允许位取反
//EA=~EA;
ET0=~ET0; //将外部中断运行位取反
num=0;
}
while(!pkey);
}
}