微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 51单片机,用郭天祥的板子做了一个电子表,发现时间很不准,求教问题在哪里

51单片机,用郭天祥的板子做了一个电子表,发现时间很不准,求教问题在哪里

时间:10-02 整理:3721RD 点击:

  1. //本程序是基于6位数码管做的电子钟
  2. //前两位显示小时,中间两位显示==,后面两位显示分钟
  3. //按键1按一次进入调整小时,按两次调整分钟,按三次恢复正常
  4. //调整小时时,小时数每秒闪一次,分钟数同理。
  5. #include <mydec.h>
  6. #include <tianxiang.h>
  7. uchar hour,min,sec;
  8. uchar count1,count2,count3,count4,count5,count6;
  9. uchar cnt1,cnt2,cnt3,key,cnt4,status;
  10. bit flag1,flag2,flag3;
  11. void main()
  12. {
  13.         flag1=0;
  14.         flag2=0;flag3=0;

  15.         //        中断控制
  16.         TMOD=0x01;
  17.         TH0=(65536-10000)/256;
  18.         TL0=(65536-10000)%256;
  19.        
  20.        
  21.         EA=1;
  22.         ET0=1;
  23.         TR0=1;
  24.         hour=19;
  25.         min=57;       


  26.         while(1)
  27.         {
  28.                 count1=hour/10;
  29.                 count2=hour%10;
  30.                 count5=min/10;
  31.                 count6=min%10;

  32.                 if(flag3)
  33.                 {
  34.                         count2=16;
  35.                         count1=16;
  36.                 }
  37.             if(flag2)
  38.           {
  39.                   count5=16;
  40.                 count6=16;
  41.           }
  42.                                 //6
  43.                            weixuan=1;
  44.                         P0=0x5f;
  45.                         weixuan=0;
  46.                        
  47.        
  48.                         duanxuan=1;
  49.                         P0=num[count6];
  50.                         duanxuan=0;               
  51.                         delay(2);
  52.                 //5
  53.                            weixuan=1;
  54.                         P0=0x6f;
  55.                         weixuan=0;
  56.                        
  57.        
  58.                         duanxuan=1;
  59.                         P0=num[count5];
  60.                         duanxuan=0;               
  61.                         delay(2);
  62.                
  63.                
  64.                 //4
  65.                    weixuan=1;
  66.                 P0=0x77;
  67.                 weixuan=0;
  68.        

  69.                 duanxuan=1;
  70.                 P0=count4;
  71.                 duanxuan=0;               
  72.                 delay(2);               
  73.                             //3
  74.                    weixuan=1;
  75.                 P0=0x7b;
  76.                 weixuan=0;
  77.        

  78.                
  79.                         duanxuan=1;
  80.                         P0=count3;
  81.                         duanxuan=0;               
  82.                         delay(2);


  83.                                         //2
  84.                            weixuan=1;
  85.                         P0=0x7d;
  86.                         weixuan=0;
  87.                
  88.        
  89.                         duanxuan=1;
  90.                         P0=num[count2];
  91.                         duanxuan=0;               
  92.                         delay(2);
  93.        
  94.                                         //1
  95.                            weixuan=1;
  96.                         P0=0x7e;
  97.                         weixuan=0;
  98.                
  99.        
  100.                         duanxuan=1;
  101.                         P0=num[count1];
  102.                        
  103.                         duanxuan=0;               
  104.                         delay(2);
  105.                
  106.        
  107. //检测按键
  108.                 if(P3!=0XFF)
  109.                 {
  110.                         delay(1);
  111.                         if(P3!=0XFF)
  112.                         {       
  113.                                 key=P3;
  114.                                 //若没松键,则不操作
  115.                                 if(flag1==0)
  116.                                 {
  117.                                         flag1=1;
  118.                                         //change mode
  119.                                         if(key==0xef)                               
  120.                                                 status++;
  121.                                                 if(status>=3)
  122.                                                 status=0;
  123.                                                 //change value
  124.                                         else if(key==0xdf)
  125.                                         {
  126.                                                 if(status==1)
  127.                                                 {
  128.                                                         hour++;
  129.                                                         hour=hour%24;
  130.                                                  }
  131.                                                  else if(status==2)
  132.                                                  {
  133.                                                          min++;
  134.                                                         min=min%60;
  135.                                                  }
  136.                                                  
  137.                                        
  138.                                         }               

  139.                                        

  140.                                   }
  141.                                                  
  142.                         }
  143.                         //无按键则按下标志清0
  144.                         else flag1=0;       
  145.                 }
  146.                 else flag1=0;
  147.        
  148.        
  149.         }  //end while




  150. }


  151. void time0() interrupt 1
  152. {
  153.         //10MS中断
  154.         TH0=(65536-10000)/256;
  155.         TL0=(65536-10000)%256;
  156.         cnt1++;
  157.         cnt2++;
  158.         cnt4++;
  159.         if(cnt2==50)
  160.         {
  161.                 cnt2=0;
  162.                 count3=count3^9;
  163.                 count4=count4^9;
  164.                
  165.                         if(status==1)
  166.                         {       
  167.                                 if(!count3)
  168.                                 flag3=1;
  169.                                 else flag3=0;
  170.                                 flag2=0;
  171.                         }
  172.                         else if(status==2)
  173.                         {
  174.                                 if(!count3)
  175.                                         flag2=1;
  176.                                 else flag2=0;
  177.                                 flag3=0;
  178.                          }
  179.                         else {flag2=0;flag3=0;}
  180.                                
  181.         }
  182.         //1秒
  183.         if(cnt1==100)
  184.         {
  185.                 cnt1=0;
  186.                 sec++;
  187.                 if(sec==60)
  188.                 {
  189.                         sec=0;
  190.                         min++;
  191.                 }
  192.                 if(min>=60)
  193.                 {
  194.                         min=0;
  195.                         hour++;
  196.                 }
  197.                 if(hour>=24)
  198.                 {
  199.                         hour=0;
  200.                 }
  201.                        


  202.                
  203.         }



  204.                
  205. }

复制代码

我在电脑上跑了下,10MS的中断,大概11MS才进入一次,1分钟少了5S,一小时少了5分钟,在板子上跑差不多也是这个误差。求教该怎么改?

把中断装入初值改下,用定时器也不会蛮准,因为中断函数也会有误差,慢慢调。我感觉就是到后面误差会越来越大,如果真要做还是用时钟芯片好

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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top