⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.txt

📁 片机电子钟的计时脉冲基准是由外部晶振的频率经过12分频后提供
💻 TXT
字号:
 

相信有很多爱好单片机的朋友都用单片机制作过电子钟,这的确是一个很好的锻炼课题。可是当在你享受成功的快乐或是在朋友面前炫耀的时候,你会突然间发现你当初对着电视校准的电子钟的时间竟然变快或是变慢了。于是你就尝试用各种方法来调整它的走时精度,但是最终的效果还是不尽人意,只好每过一段时间手动调整一次了。渐渐的你有点烦了,不再去管它或是直接弃之不用。 
我和大家一样对此深有体会,于是我开始查找翻阅资料,试图找出一个解决的好方法。终于有一天…… 
废话太多——stop 
原因分析: 
1.                  单片机电子钟的计时脉冲基准是由外部晶振的频率经过12分频后提供,采用内部的定时/计数器来实现计时功能。所以,外接晶振频率精确度直接影响电子钟计时的准确性。 
2.                  单片机电子钟利用内部定时/计数器溢出产生中断(12M晶振一般为50ms)再乘以相应的倍率来实现秒、分、时的转换。大家都知道从定时/计数器产生中断请求到响应中断需要3-8个机器周期(如不明白请参考其它资料),定时中断子程序中的数据入栈和重装定时/计数器的初值还需要占用数个机器周期,还有从中断入口转到中断子程序也要占用一定的机器周期。    例如: 
       ORG       00H
       LJMP      START
       ORG       0BH
       LJMP      TIMER                 ;2个机器周期 
       ORG       30H
START:
       MOV      30H,       #0          
       MOV      31H,       #0
       MOV      32H,       #0
       MOV      33H,       #0
       MOV      20H,       #10        
       MOV      21H,       #2
       MOV      SP,   #40H             
       MOV      IP,   #00H
       MOV      IE,   #82H                     ;开EA﹑ET0
       MOV      TMOD,   #01H              ;定时器模式1      
       MOV      TH0,       #03CH           ;50MS初裝值
       MOV      TL0,       #0B0H
       SETB      TR0                             ;启动TR0
LOOP:
       ……
TIMER:                                             ;定時器中断子程序
       PUSH      ACC                            ;2个机器周期 
       PUSH      PSW                            ;2个机器周期 
       MOV      TL0,              #0B0H+6+3          
       MOV      TH0,       #03CH
       ……
                            RETI
                            END      
从上面的例子大家可以看出从中断入口到定时/计数器初值的低8位装入需要占用2+2+2=6个机器周期。所以我们在编程时一般会把这8个机器周期加入定时/计数器的初值。但是从定时/计数器溢出中断请求到执行中断需要几个机器周期(3-8个机器周期)我们很难确定其准确值,因此导致了电子钟计时不准。 
解决方法: 
1.                采用高精度晶振方案
虽然采用高精度的晶振可以稍微提高电子钟计时的精确度,但是其并不是导致电子钟计时不准的主要因素,而且高精度的晶振价格较高,所以不必采用此方案。 
2.                动态同步修正方案
从程序入手,采用动态同步修正方法给定时/计数器赋初值。动态同步修正方法:由于定时/计数器溢出后又会从0开始自动加数,固在给定时/计数器再次赋值前将定时/计数器低位(TL0)中的值和初始值相加后一并送入定时/计数器中,此时定时/计数器中的值即为动态同步修正后的准确值。例如: 
                 TIMER:                                  
                 PUSH ACC 
                 PUSH PSW 
                 MOV  A, #0B0H 
                 ADD   A, TL0                      ;初值和TL0中的数相加即为同步修正值 
                 MOV  TL0,       A                  ;修正值送定时/计数器低8位 
                 MOV  TH0,      #03CH 
                 …… 
                 
                 RETI 
采用了此种方法后相信你的电子钟的精度已经大大提高了。别走开,后面内容更精彩。 
3.                自动调整方案
采用了同步修正方案后电子钟的精度虽然提高了很多,但是由于晶振频率的偏差和一些其它未知因素(同一块电路板、同样的程序换了一片单片机后走时误差却不一样,不知是何原因)的影响,时间长了仍然会有积累误差。为此我设计出了此自动调整方案,实际也是一种容错技术。其自动调整原理为:实测出误差1秒所需的时间,然后每隔这样一段时间后就对秒进行加1或减一调整。例如:电子钟每过50小时就慢1秒,其自动调整程序如下: 
                 TIMER:                                                ;定時中斷程序 
                 PUSH ACC                                  ;數據保護 
                 PUSH PSW 
                 …… 
T_3: 
                 INC    A_1 
                 MOV  A,   A_1 
                 CJNE  A,   #50,       RETI_1         ;到50小时了吗? 
                 INC    S_1                                    ;到50小时秒加1 
                 MOV  A_1,      #OOH   
RETI_1: 
                 POP    PSW 
                 POP    ACC 
                 RETI 
使用此方法调整较费时间,但是效果非常好,经实验一次调整可以将月误差控制在1秒左右,如按此方法再次测出误差1秒所需的天数并进行二次调整,其精度会更高。 
电子钟源程序:(修改后)修改前的源程序可以到论坛<单片机技术交流>里看我发的<简单的电子钟源程序>一文 
           S_1     EQU      30H                            ;秒寄存器 
           M_1    EQU      31H                            ;分寄存器 
           H_1    EQU      32H                            ;時寄存器 
           A_1    EQU      33H                            ;自动调整寄存器 
           ORG   00H 
           LJMP  START 
           ORG   03H 
           RETI 
           ORG   0BH                                   ;定時中斷入口 
           LJMP  TIMER         
           ORG   13H 
           RETI 
           ORG   1BH 
           RETI 
           ORG   30H 
START: 
           MOV  S_1,       #0                        ;秒、分、時寄存器清0 
           MOV  M_1,      #0 
           MOV  H_1,      #0 
           MOV  A_1,      #0 
           MOV  20H,      #10                      ;0.5秒鐘中斷次數,0.5s=500ms=50msx10 
           MOV  21H,      #2                      ;2個0.5秒即為1秒 
           MOV  SP,  #40H                          ;堆棧指針設置 
           MOV  IE,   #82H                          ;開定時器0中斷及總中斷 
           MOV  TMOD,  #01H                          ;定時器0模式1 
           MOV  TH0,      #03CH                        ;50ms初值 
           MOV  TL0,       #0B0H 
           SETB  TR0                                   ;啟動定時器0 
LOOP: 
           ACALL     DISP                                  ;調用顯示 
           JNB    P3.4,      MT                      ;查詢分調整鍵 
           JNB    P3.5,      HT                       ;查詢時調整鍵 
           AJMP LOOP 
MT:                                            ;分調整 
           ACALL     DISP 
           JNB    P3.4,      MT                      ;鍵消抖 
           INC    M_1                                   ;分加1 
           MOV  A,   M_1                     
           CJNE  A,   #60,       LOOP                  ;沒到60分返回,到60分清0    
           MOV  M_1,      #0 
           AJMP LOOP 
HT:                                             ;時調整 
           ACALL     DISP 
           JNB    P3.5,      HT 
           INC    H_1 
           MOV  A,   H_1 
           CJNE  A,   #24,       LOOP 
           MOV  H_1,      #0 
           AJMP LOOP 
DISP:                                         ;顯示子程序 
           MOV  DPTR,   #NUMTAB                        ;表地址送數據指針 
           MOV  A,   M_1                            ;分送A 
           MOV  B,    #10               
           DIV    AB                              ;十進制調整 
           ADD   A,   R0                        ;查表偏移量調整 
           MOVC      A,   @A+DPTR                        ;查表     
           MOV  P1,  A                         ;分十位送p1口顯示 
           CLR    P3.2                                   ;開分十位顯示 
           ACALL     D1MS                                ;延時1ms 
           SETB  P3.2                                   ;關顯示 
           MOV  A,   B                          ;分個位p1口顯示           
           ADD   A,   R0                 
           MOVC      A,   @A+DPTR 
           MOV  P1,  A 
           CLR           P3.3 
           ACALL     D1MS 
           SETB  P3.3 
           MOV  A,   H_1                            ;時送A 
           MOV  B,    #10 
           DIV    AB 
           ADD   A,   R0 
           MOVC      A,   @A+DPTR 
           MOV  P1,  A                  
           CLR    P3.0                                   ;顯示時十位 
           ACALL     D1MS 
           SETB  P3.0 
           MOV  A,   B 
           ADD   A,   R0 
           MOVC      A,   @A+DPTR 
           MOV  P1,  A 
           CLR    P3.1                                   ;顯示時個位 
           ACALL     D1MS 
           SETB  P3.1 
           RET                                       ;返回 
TIMER:                                             ;定時中斷程序 
           PUSH ACC                                  ;數據保護 
           PUSH PSW 
           MOV  A,   #0B0H                        ;同步修正 
           ADD   A,   TL0 
           MOV  TL0,       A                         ;重置50ms定時值 
           MOV  TH0,      #03CH 
           DJNZ  20H,      RETI_1                       ;到0.5秒了嗎? 
           MOV  20H,      #10 
           CPL    25H.0                                ;取反秒點閃爍標志位 
           JNB    25H.0,   T_1                      ;標志位為0轉T_1 
           MOV  R0,  #0                        ;查表偏移量寄存器置0(不顯示秒點) 
           AJMP T_2 
T_1: 
           MOV  R0,  #10                      ;查表偏移量寄存器置10(顯示秒點,秒點每秒閃爍1次) 
T_2:    
           DJNZ  21H,      RETI_1                       ;到1秒了嗎? 
           MOV  21H,      #2 
           INC    S_1                             ;秒加1 
           MOV  A,   S_1 
           CJNE  A,   #60,       RETI_1                ;到60秒了嗎? 
           MOV  S_1,       #0                        ;到60秒清0 
           INC    M_1                                   ;分加1 
           MOV  A,   M_1 
           CJNE  A,   #60,       RETI_1                ;到60分了嗎? 
           MOV  M_1,      #0 
           INC    H_1                                   ;時加1 
           MOV  A,   H_1 
           CJNE  A,   #24,       T_3               ;到24小時了嗎? 
           MOV  H_1,      #00H 
T_3:                                                         ;自动调整 
           INC    A_1 
           MOV  A,   A_1 
           CJNE  A,   #50,       RETI_1 
           INC    S_1 
           MOV  A_1,      #OOH   
RETI_1: 
           POP    PSW 
           POP    ACC 
           RETI 
D1MS:                                              ;1毫秒延時 
           MOV  R7,  #2 
D_1: 
           MOV  R6,  #250 
           DJNZ  R6,  $ 
           DJNZ  R7,  D_1 
           RET 
NUMTAB: 
           DB      10H,0D3H,48H,41H,83H,21H,20H,53H,00H,01H;不顯示秒點 
           DB      14H,0D7H,4CH,45H,87H,25H,24H,57H,04H,05H;顯示秒點 
           END   
由于本人接触单片机的时间不长,文章中难免有错误之处,还请大家多指教。如有其他问题可以在论坛上讨论。本文可以自由传播,但请注明作者及出处
参考链接:http://www.picavr.com/news/2008-05/5343.htm

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -