51单片机,用郭天祥的板子做了一个电子表,发现时间很不准,求教问题在哪里
- //本程序是基于6位数码管做的电子钟
- //前两位显示小时,中间两位显示==,后面两位显示分钟
- //按键1按一次进入调整小时,按两次调整分钟,按三次恢复正常
- //调整小时时,小时数每秒闪一次,分钟数同理。
- #include <mydec.h>
- #include <tianxiang.h>
- uchar hour,min,sec;
- uchar count1,count2,count3,count4,count5,count6;
- uchar cnt1,cnt2,cnt3,key,cnt4,status;
- bit flag1,flag2,flag3;
- void main()
- {
- flag1=0;
- flag2=0;flag3=0;
- // 中断控制
- TMOD=0x01;
- TH0=(65536-10000)/256;
- TL0=(65536-10000)%256;
-
-
- EA=1;
- ET0=1;
- TR0=1;
- hour=19;
- min=57;
- while(1)
- {
- count1=hour/10;
- count2=hour%10;
- count5=min/10;
- count6=min%10;
- if(flag3)
- {
- count2=16;
- count1=16;
- }
- if(flag2)
- {
- count5=16;
- count6=16;
- }
- //6
- weixuan=1;
- P0=0x5f;
- weixuan=0;
-
-
- duanxuan=1;
- P0=num[count6];
- duanxuan=0;
- delay(2);
- //5
- weixuan=1;
- P0=0x6f;
- weixuan=0;
-
-
- duanxuan=1;
- P0=num[count5];
- duanxuan=0;
- delay(2);
-
-
- //4
- weixuan=1;
- P0=0x77;
- weixuan=0;
-
- duanxuan=1;
- P0=count4;
- duanxuan=0;
- delay(2);
- //3
- weixuan=1;
- P0=0x7b;
- weixuan=0;
-
-
- duanxuan=1;
- P0=count3;
- duanxuan=0;
- delay(2);
- //2
- weixuan=1;
- P0=0x7d;
- weixuan=0;
-
-
- duanxuan=1;
- P0=num[count2];
- duanxuan=0;
- delay(2);
-
- //1
- weixuan=1;
- P0=0x7e;
- weixuan=0;
-
-
- duanxuan=1;
- P0=num[count1];
-
- duanxuan=0;
- delay(2);
-
-
- //检测按键
- if(P3!=0XFF)
- {
- delay(1);
- if(P3!=0XFF)
- {
- key=P3;
- //若没松键,则不操作
- if(flag1==0)
- {
- flag1=1;
- //change mode
- if(key==0xef)
- status++;
- if(status>=3)
- status=0;
- //change value
- else if(key==0xdf)
- {
- if(status==1)
- {
- hour++;
- hour=hour%24;
- }
- else if(status==2)
- {
- min++;
- min=min%60;
- }
-
-
- }
-
- }
-
- }
- //无按键则按下标志清0
- else flag1=0;
- }
- else flag1=0;
-
-
- } //end while
- }
- void time0() interrupt 1
- {
- //10MS中断
- TH0=(65536-10000)/256;
- TL0=(65536-10000)%256;
- cnt1++;
- cnt2++;
- cnt4++;
- if(cnt2==50)
- {
- cnt2=0;
- count3=count3^9;
- count4=count4^9;
-
- if(status==1)
- {
- if(!count3)
- flag3=1;
- else flag3=0;
- flag2=0;
- }
- else if(status==2)
- {
- if(!count3)
- flag2=1;
- else flag2=0;
- flag3=0;
- }
- else {flag2=0;flag3=0;}
-
- }
- //1秒
- if(cnt1==100)
- {
- cnt1=0;
- sec++;
- if(sec==60)
- {
- sec=0;
- min++;
- }
- if(min>=60)
- {
- min=0;
- hour++;
- }
- if(hour>=24)
- {
- hour=0;
- }
-
-
- }
-
- }
把中断装入初值改下,用定时器也不会蛮准,因为中断函数也会有误差,慢慢调。我感觉就是到后面误差会越来越大,如果真要做还是用时钟芯片好
1小时差5分钟的原因在于你的工作方式选择不正确,方式1在每次中断后需要重新给定时器赋初值。修改如下:
标准51的时钟频率只能使用6MHz、12MHz或24MHz;假设时钟频率为12MHz,则每秒钟有1M个机器周期。
在main()的前面定义一个16位无符号整型变量,用来讲录中断次数,例如:
unsigned int temp=0; //用来计1秒钟的中断次数
定时器初始化语句:
TMOD=0x02; //自动重载初值的8位计数器
TH0=6;
TL0=6; //中断一次共250个机器周期
按上面的设置,每秒钟中断4000次,T0的参考中断服务函数如下:
void timer0() interrupt 1
{
temp++;
if(temp==4000)
{
temp=0;
sec++;
if(sec==60)
{
sec=0;
min++;
if(min==60)
{
min=0;
hour++;
if(hour==24)
hour=0;
}
}
}
}
中断服务函数需要标志位的修改请自己完成。
单片机的主频累计的误差大,不可能做电子表。
晶振频率是11.0592Mhz的吧
时间的处理不要在中断中做,不然很可能会有孔径误差。在中断中设个标志,在外面做秒钟加1