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