上一个数字钟程序有点问题,继续DIY如下: 源代码如下: //4个数码管依次显示时分,秒用LED灯,4个按键,按SW1,显示日历或时间 ,SW2,相应显示高位加一,SW3,相应显示低位减一 #include<reg51.h> #include<absacc.h> #define uchar unsigned char #define uint unsigned int uchar *dis_ptr; uchar data dis_buf[4]={0,0,0,0};//显示缓冲区 uchar data time_buf[3]={0x00,0x00,0x00};//时钟显示数据 uchar data date_buf[2]={0x0b,0x04};//日历显示数据 uchar code seg_tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82, 0xf8,0x80,0x90,0xff};//7段共阴极,依次为0-9 uchar code digit_tab[4]={1,2,4,8};//动态显示缓冲区 uint m=0; uint n=0; uint p=0; uint key_flag=0; sbit p10=P1^0;//接LED灯,低电平有效 sbit p24=P2^4;//SW1 sbit p25=P2^5;//SW2 sbit p26=P2^6;//SW3 void init_sys(); void disply_one(void); void dis_buf_flash(void); bit key_test(void); void key(void); void key_delay(); void main() {init_sys(); for(;;);} void init_sys(void)//T0工作于方式2,定时250um, { dis_ptr=dis_buf+3; TH0=6; TL0=6; TMOD=2; IE=0x82; IP=2; TR0=1;
}
void disply_one(void)//动态显示1位 {uchar i; P0=seg_tab[*dis_ptr]; i=dis_ptr-dis_buf; P2=~digit_tab; if (dis_ptr>dis_buf) dis_ptr--; else dis_ptr=dis_buf+3; }
void dis_buf_flash(void)//显示数据送缓冲区 {if(p%2==1)//刷新日历 { dis_buf[0]=date_buf[0]/10; dis_buf[1]=date_buf[0]%10; dis_buf[2]=date_buf[1]/10; dis_buf[3]=date_buf[1]%10; } else//刷新时间 {dis_buf[0]=time_buf[0]/10; dis_buf[1]=time_buf[0]%10; dis_buf[2]=time_buf[1]/10; dis_buf[3]=time_buf[1]%10;} }
void time0(void) interrupt 1 { dis_buf_flash(); disply_one(); TF0=0; m++; n++; if(key_test()==0) {key_flag=0;} if ((n>=40)&&(key_flag==0))//10ms扫描键盘 {n=0; key_test();//扫描键盘 if(key_test()==1){ key_delay(); if(key_test()==1) {key();} } } if(m>=2000){p10=0;} if (m>=4000)//1秒处理 { m=0; p10=1; time_buf[2]+=1; if(time_buf[2]>=60)//60秒处理 {time_buf[2]=0; time_buf[1]+=1;} if (time_buf[1]>=60)//60分处理 {time_buf[1]=0; time_buf[0]+=1;} if (time_buf[0]>=24)//24小时处理 { time_buf[0]=0; time_buf[1]=0; time_buf[2]=0; date_buf[1]+=1; } if(date_buf[1]>=30)//30天处理 {date_buf[1]=1; date_buf[0]+=1;} if(date_buf[0]>=13)//12个月处理 {date_buf[0]=1; date_buf[1]=1;} } } bit key_test(void)//测试键盘有无键按下 { if ((p24==0)||(p25==0)||(p26==0)) return ((bit)1); else return ((bit)0); }
void key(void)//按键处理 {key_flag=1;//置标志,停止键盘扫描! if(p24==0) {++p; }
else if(p25==0){if(p%2==1){date_buf[0]+=1;}//高位区域加一 else time_buf[0]+=1; } else {if(p%2==1){date_buf[1]+=1;}//低位区域加一 else time_buf[1]+=1; }
}
void key_delay()//去抖动 {uchar i,s; for(i=10000,s=5;s>=1;i--) {s=i;} } 程序能正常执行,显示 但时间误差太大! 达到60:100 分析可能有什么程序断在中断中被延时! 调试后发现问题出在中断中的 if(key_test()==0) {key_delay(); if(key_test()==0) {key_flag=0;} } 因为我设置了标志位用来标志有键按下时停止扫描键盘!无键按下时扫描键盘, 这就导致没键按下时,每次都要延迟,一个中断延时一次,1秒下来就误差很多了 解决办法:把上述程序段中的延时程序去了!再经调试,能准确显示了!
请大家多多指教!
|