我用这个代码都可以,代码有点长,可能还有点乱,中间好像还有bug,还没找到,中断扫描16个键有的好用,有的不好用。
#include <REG51.H>
int shi_gao,shi_di,fen_gao,fen_di,miao_gao,miao_di; // 秒个位,十位、分个位、十位
unsigned char Tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
int num,set_time,time_1,time_2,time_3,time_4;
sbit P11=P1^0;
sbit P12=P1^1;
sbit P13=P1^2;
sbit P14=P1^3;
sbit beep=P1^4;
sbit stp_clk=P1^5;
int zhongduan_cnt;
//10ms延时子程序(12MHZ)
void delay_ms(void)
{
int i,j,k;
for(i=5;i>0;i--)
for(j=4;j>0;j--)
for(k=248;k>0;k--);
}
void delay_qudou(int z)
{
int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void init()
{
TMOD=0x01; //定时器初始化 选择timer0做16位定时器
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1; //开放中断
ET0=1; //开放timer0中断
TR0=1; //启动timer0
EX0=1;// 按键外部中断用
IT0=1; // 按键外部中断用
}
void display(int shi_gao,shi_di,fen_gao,fen_di)
{
P2 = 0X00;
P14=1;
P2=Tab[shi_gao];
delay_ms() ;
P14=0;
P2 = 0X00;
P13=1;
P2=Tab[shi_di];
delay_ms() ;
P13=0;
P2 = 0X00;
P12=1;
P2=Tab[fen_gao];
delay_ms() ;
P12=0;
P2 = 0X00;
P11=1;
P2=Tab[fen_di];
delay_ms() ;
P11=0;
}
void Delay_beep(int x)
{ int t; while(x--) for(t=0;t<120;t++); } //按周期t发音
void Play(int t)
{ int i; for(i=0;i<100;i++) { beep=~beep; Delay_beep(t); } beep=0; }
void timer0(void) interrupt 1 using 1
{
TH0 = (65536-50000)/256;
TL0= (65536-50000)%256;
zhongduan_cnt++;
}
void is_key(void) interrupt 0 using 1 //stop clok
{
miao_di=0;
miao_gao=0;
fen_di=0;
fen_gao=0;
shi_di=0;
shi_gao=0;
set_time=0;
stp_clk=1;
while(1)
{
keyscan();
display(shi_gao,shi_di,fen_gao,fen_di);
if (set_time==4)
break;
}
}
//用uchar keyscan() 带返回值的函数
int keyscan(uchar){
int temp;
P0= 0xf7; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求
temp =P0;//读回来了
temp &= 0xf0;//因为我们只是读回来高4位
while (temp != 0xf0){
delay_qudou(5);//消除抖动的
temp=P0;
temp &= 0xf0;
while(temp != 0xf0){ //确实不等于0xf0有按键按下
temp = P0;//我们这个时候只是把P3口的值赋给了temp
switch (temp){ //检测P3口。
case 0xe7:
num =3 ;
break;
case 0xd7:
num=4;
break;
case 0xb7:
num=5;
break;
case 0x77:
num=6;
break;
}
set_time=set_time+1;
if (set_time==1)
{
if (num>2)
{set_time=set_time-1;}
else
shi_gao=num;
}
if (set_time==2)
if (shi_gao==2 && num>3)
{set_time=set_time-1;}
else
shi_di=num;
if (set_time==3)
{
if (num>5)
{set_time=set_time-1;}
else
fen_gao=num;
}
if (set_time==4)
fen_di=num;
while(temp != 0xf0)//有按键按下可能是不等于的 循环在这里面 松手检测
{
temp = P0;
temp = temp & 0xf0; //这个是松手检测 松手这里就等于了0xf0
}//下面就显示一下 退出整个4行循环。不加松手检测会退不出去循环
//到这里是把第4行检测了。
}
}
P0= 0xfb; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求
temp =P0;//读回来了
temp &= 0xf0;//因为我们只是读回来高4位
while (temp != 0xf0){
delay_qudou(5);//消除抖动的
temp=P0;
temp &= 0xf0;
while(temp != 0xf0){ //确实不等于0xf0有按键按下
temp = P0;//我们这个时候只是把P3口的值赋给了temp
switch (temp){ //检测P3口。
case 0xeb:
num =9;
break;
case 0xdb:
num=0;
break;
case 0xbb:
num=1;
break;
case 0x7b:
num=2;
break;
}
set_time=set_time+1;
if (set_time==1)
{
if (num>2)
{set_time=set_time-1;}
else
shi_gao=num;
}
if (set_time==2)
if (shi_gao==2 && num>3)
{set_time=set_time-1;}
else
shi_di=num;
if (set_time==3)
{
if (num>5)
{set_time=set_time-1;}
else
fen_gao=num;
}
if (set_time==4)
fen_di=num;
while(temp != 0xf0)//有按键按下可能是不等于的 循环在这里面 松手检测
{
temp = P0;
temp = temp & 0xf0; //这个是松手检测 松手这里就等于了0xf0
}//下面就显示一下 退出整个3行的循环。 不加松手检测会退不出去循环
//到这里是把第3行检测了。
}
}
P0= 0xfd; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求
temp =P0;//读回来了
temp &= 0xf0;//因为我们只是读回来高4位
while (temp != 0xf0){
delay_qudou(5);//消除抖动的
temp=P0;
temp &= 0xf0;
while(temp != 0xf0){
temp = P0;
switch (temp){
case 0xed:
num = 5;
break;
case 0xdd:
num=6;
break;
case 0xbd:
num=7;
break;
case 0x7d:
num=8;
break;
}
set_time=set_time+1;
if (set_time==1)
{
if (num>2)
{set_time=set_time-1;}
else
shi_gao=num;
}
if (set_time==2)
if (shi_gao==2 && num>3)
{set_time=set_time-1;}
else
shi_di=num;
if (set_time==3)
{
if (num>5)
{set_time=set_time-1;}
else
fen_gao=num;
}
if (set_time==4)
fen_di=num;
while(temp != 0xf0)//有按键按下可能是不等于的 循环在这里面 松手检测
{
temp = P0;
temp = temp & 0xf0; //这个是松手检测 松手这里就等于了0xf0
}
//到这里是把第2行检测了。
}
}
P0= 0xfe; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求
temp =P0;//读回来了
temp &= 0xf0;//因为我们只是读回来高4位
while (temp != 0xf0){ //下面的几个while循环判断可以用if好理解。只看到第一行就行了。有按键按下可能是不等于的,不加松手检测会退不出去循环
delay_qudou(5);//消除抖动的
temp=P0;
temp &= 0xf0;
while(temp != 0xf0){ //确实不等于0xf0有按键按下
temp = P0;//我们这个时候只是把P0口的值赋给了temp
switch (temp){ //检测P0口。
case 0xee:
num = 1;
break;
case 0xde:
num=2;
break;
case 0xbe:
num=3;
break;
case 0x7e:
num=4;
break;
}
set_time=set_time+1;
if (set_time==1)
{
if (num>2)
{set_time=set_time-1;}
else
shi_gao=num;
}
if (set_time==2)
if (shi_gao==2 && num>3)
{set_time=set_time-1;}
else
shi_di=num;
if (set_time==3)
{
if (num>5)
{set_time=set_time-1;}
else
fen_gao=num;
}
if (set_time==4)
fen_di=num;
while(temp != 0xf0)//有按键按下可能是不等于的 循环在这里面 松手检测
{
temp = P0;
temp = temp & 0xf0; //这个是松手检测 松手这里就等于了0xf0
}
//到这里是把第一行检测了。以下下是其他几行检测的代码
}
}
}
/*********主程序********************/
void main()
{
beep=0;
miao_di=0;
miao_gao=0;
fen_di=5;
fen_gao=0;
shi_di=7;
shi_gao=0;
zhongduan_cnt=0;
stp_clk=0;
P11=0;
P12=0;
P13=0;
P14=0;
init();
while(1)
{
if(zhongduan_cnt>19) //如果到了1S
{
zhongduan_cnt=0; //清零
if(shi_gao==0 && shi_di==7 && fen_gao==0 && fen_di==0 && stp_clk==0) //0700始响
{ Play(2);}
if (shi_gao==2 && shi_di==3 && fen_gao==5 && fen_di==9) //是否跨天
{
shi_gao=0 ;
shi_di=0 ;
fen_gao=0;
fen_di=0;
}
else
{
miao_di++; //秒数累加
if (miao_di>9)
{
miao_gao=miao_gao+1;
miao_di=0;
}
if (miao_gao>5)
{
fen_di=fen_di+1;
miao_gao=0;
}
if (fen_di>9)
{
fen_gao=fen_gao+1;
fen_di=0;
}
if (fen_gao>5)
{
shi_di=shi_di+1;
fen_gao=0;
}
if (shi_di>9)
{
shi_gao=shi_gao+1;
shi_di=0;
}
}
}
display(shi_gao,shi_di,fen_gao,fen_di);
}
}
|