单片机4位数字时钟仿真程序(定时器方式2, 按键连加)
2020-09-21 来源:51hei
学习单片机动态数码管显示,数字时钟是最好的案例,本仿真案例有以下特点。
1.使用定时器0,方式2,可以减小定时器的误差;
2.调时、调分按键具有连加功能,与常见的按键松手检测有区别;
3.具有秒点显示功能,若制作实物案例,可购买带秒点的数码管。
参考程序:
#include
#define uint unsigned int
#define uchar unsigned char
sbit w1=P2^2;
sbit w2=P2^3;
sbit w3=P2^4;
sbit w4=P2^5;
sbit s1=P1^3;
sbit s2=P1^4;
sbit s3=P1^5;
uint shi,fen,sec;
uint num,s1num,keynum;
uchar m;
void delay(uint);
void keyscan();
void time_adj();
uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00}; //共阴代码
void display() //数码管显示
{
w1=1;w2=1;w3=1;w4=1;
P0=~tab[shi/10%10];
if((s1num==2)|(shi/10%10==0)){w1=1;}
else{w1=0;}
delay(5);
w1=1;
if(num<2000)
{P0=~(tab[shi%10]|0x80); } //秒点显示
else
{P0=~tab[shi%10];}
if(s1num==2){w2=1;}
else{w2=0;}
delay(5);
w2=1;
P0=~tab[fen/10%10];
if(s1num==1){w3=1;}
else{w3=0;}
delay(5);
w3=1;
P0=~tab[fen%10];
if(s1num==1){w4=1;}
else{w4=0;}
delay(5);
w4=1;
}
void keyscan() //功能键函数
{
if(s1==0)
{
delay(5); //消抖
if(s1==0)
{
while(!s1)display();
s1num++;
if(s1num==3)
{
s1num=0;
}
}
}
}
void time_adj() //加、减键时间调整函数
{
if(s1num!=0)
{
if(s2==0)
{
keynum++;
if(keynum>18) //连加延时
{
switch(s1num)
{
case 1:
shi++;
if(shi>23)
{shi=0;}
keynum=0;
break;
case 2:
fen++;
if(fen>59)
{fen=0;}
keynum=0;
break;
}
}
}
if(s3==0)
{
keynum++;
if(keynum>18)
{
switch(s1num)
{
case 1:
shi--;
if(shi<0)
{shi=23;}
keynum=0;
break;
case 2:
fen--;
if(fen<0)
{fen=59;}
keynum=0;
break;
}
}
}
}
}
void main()
{
shi=12;fen=0;sec=0;num=0;
TMOD=0x02;
TH0=0x06;
TL0=0x06;
EA=1;
ET0=1;
TR0=1;
while(1)
{
keyscan();
time_adj();
display();
if(sec>59)
{
sec=0;
fen++;
if(fen>59)
{
fen=0;
shi++;
if(shi>23)
{
shi=0;
}
}
}
}
}
void delay(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void Timer0() interrupt 1 //定时器服务
{
num++;
if(num==4000){num=0;sec++;}
}