標(biāo)題: 用單片機(jī)制作最高精度時(shí)間系統(tǒng),可移植到任何時(shí)鐘程序中 [打印本頁(yè)]

作者: npn    時(shí)間: 2016-9-27 18:36
標(biāo)題: 用單片機(jī)制作最高精度時(shí)間系統(tǒng),可移植到任何時(shí)鐘程序中
用單片機(jī)制作最高精度時(shí)間系統(tǒng),可移植到任何時(shí)鐘程序中
可移植到任何數(shù)字時(shí)鐘程序中,根據(jù)單片機(jī)型號(hào)以及晶振頻率修改TH0和TL0的值。
智能日期時(shí)間累加,平閏年判斷,當(dāng)月天數(shù)判斷功能,年計(jì)數(shù)值0~9999。
使用1秒的延遲函數(shù),再加上時(shí)間判斷計(jì)數(shù)函數(shù)的時(shí)間,誤差非常大。
采用5毫秒定時(shí)器中斷計(jì)數(shù),中斷觸發(fā)后重置計(jì)數(shù)值并且5毫秒計(jì)數(shù)加1。
處理5毫秒計(jì)數(shù)以及時(shí)間判斷計(jì)數(shù)函數(shù),定時(shí)器仍在計(jì)數(shù),準(zhǔn)確觸發(fā)高精度的5毫秒中斷。
5毫秒計(jì)數(shù)加到200時(shí),5毫秒計(jì)數(shù)清零并且觸發(fā)時(shí)間計(jì)數(shù)函數(shù),包含所有判斷日期時(shí)間的指令在5毫
秒內(nèi)完成,如5毫秒內(nèi)無(wú)法完成請(qǐng)改成更長(zhǎng)毫秒時(shí)間中斷1次,避免出現(xiàn)中斷重入等問(wèn)題。
若發(fā)現(xiàn)bug或其他建議意見請(qǐng)及時(shí)在樓下回復(fù)。
下面是源碼:


  1. #include "reg51.h"
  2. #include "intrins.h"
  3. sfr AUXR   = 0x8E;
  4. sbit led=P3^2; //秒閃爍指示燈
  5. #define ui unsigned int
  6. #define uc unsigned char
  7. ui y; //定義變量年
  8. uc m,d,h,i,s,w; //定義變量月、日、時(shí)、分、秒、周
  9. uc ms5; //5毫秒定時(shí)器中斷計(jì)數(shù)
  10. void InitTimer0(void){ //初始化5毫秒定時(shí)器,根據(jù)晶振頻率修改TH0和TL0的值。
  11.     TMOD = 0x01;
  12.     TH0 = 0x28;
  13.     TL0 = 0x00;
  14.     EA = 1;
  15.     ET0 = 1;
  16.     TR0 = 1;
  17. }

  18. bit if_leap_year(ui y){ //平閏年檢測(cè),閏年返回1,平年返回0
  19.   //閏年是4的倍數(shù)且不是100的倍數(shù)或者是400的倍數(shù),否則是平年。
  20. if((y%4 == 0 && y%100 != 0) || y%400 == 0){
  21. return 1; //返回1表示閏年
  22. } else { //否則就是平年
  23. return 0; //返回0表示平年
  24. }
  25. }
  26. uc get_mon_day_nbr(ui y,uc m){ //通過(guò)年月獲取該月有多少天
  27. if(m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) { //大
  28. 月則31天
  29.   return 31;
  30. }
  31. if(m == 4 || m == 6 || m == 9 || m == 11){ //小月則30天
  32.   return 30;
  33. }
  34.   if(m == 2){ //2月
  35.    if(if_leap_year(y) == 1){ //閏年29天
  36.    return 29;
  37.    } else { //平年28天
  38.    return 28;
  39.    }
  40.   }
  41. return 0;
  42. }

  43. bit dt_is_ok(ui y,uc m,uc d,uc w,uc h,uc i,uc s){ //檢測(cè)設(shè)置的日期時(shí)間格式是否有效 1有
  44. 效0無(wú)效
  45. if(w > 7 || w < 1) return 0; //星期大于7或小于1 返回0
  46. if(y > 9999 || m > 12 || m < 1 || d < 1) return 0; //年大于999 或 月大于12 或
  47. 月小于1 或日小于1 返回0
  48. if(d > get_mon_day_nbr(y,m)) return 0; //通過(guò)年月獲取當(dāng)月天數(shù) 大于該值 返回0
  49. if(h > 23 || i > 59 || s > 59) return 0; //時(shí)大于23 或 分大于59 或秒大于59 返回
  50. 0
  51. return 1; //檢測(cè)有效 返回1
  52. }
  53. bit set_time(ui yy,uc mm,uc dd,uc ww,uc hh,uc ii,uc ss){ //設(shè)置日期時(shí)間
  54.   if(dt_is_ok(yy,mm,dd,ww,hh,ii,ss) == 1){  //檢查日期時(shí)間格式有效
  55.   y=yy;m=mm;d=dd;w=ww; //設(shè)置年月日周
  56.   h=hh;i=ii;s=ss; //設(shè)置時(shí)分秒
  57.   return 1;  //設(shè)置成功 返回1
  58.   } else { //格式無(wú)效 返回0
  59.   return 0;
  60. }
  61. }

  62. void add_time(){ //時(shí)間步進(jìn)1秒
  63. s++; //秒加1
  64. if(s>=60){ //秒加到60
  65. s=0; //秒清零
  66. i++; //分加1
  67.   if(i>=60){ //分加到60
  68.   i=0; //分清零
  69.   h++; //時(shí)加1
  70.    if(h>=24){ //時(shí)加到24
  71.    h=0; //時(shí)清零
  72.    d++; //日加1
  73.    w++; //星期加1
  74.    if(w > 7){ //星期超過(guò)7
  75.    w=1; //星期等于1
  76.    }
  77.     if(d > get_mon_day_nbr(y,m)){  //日超過(guò)當(dāng)前年月的天數(shù)
  78.     d=1; //日清1
  79.     m++; //月加1
  80.      if(m > 12){ //月加到12以上
  81.      m=1; //月清1
  82.      y++; //年加1
  83.       if(y >= 10000){ //年加到10000
  84.       y=0; //年清零
  85.       }
  86.      }
  87.     }
  88.    }
  89.   }
  90. }
  91. }
  92. void main(){ //入口函數(shù),上電復(fù)位后在此開始執(zhí)行指令。
  93. P3=0xFF; //設(shè)置P3口全部為高電平
  94. set_time(2000,1,1,6,0,0,0); //設(shè)置日期時(shí)間
  95.     AUXR |= 0x80;  //關(guān)閉定時(shí)器0的12分頻
  96.     InitTimer0(); //初始化5毫秒定時(shí)器
  97. //死循環(huán)內(nèi)可添加其他程序,只有中斷觸發(fā)后退出,中斷返回后繼續(xù)在原地運(yùn)行程序。
  98.   while(1);

  99.   }
  100. void Timer0Interrupt(void) interrupt 1{ //5毫秒定時(shí)器中斷
  101. //重置TH0與TL0的值,根據(jù)晶振頻率修改TH0和TL0的值。
  102.     TH0 = 0x28;
  103.     TL0 = 0x00;
  104.    ms5++; //5毫秒中斷計(jì)數(shù)加1
  105.     if(ms5%100 == 0)led=~led;
  106.      //5毫秒中斷計(jì)數(shù)加到200 200*5=1000毫秒 1秒觸發(fā)1次
  107.     if(ms5 >= 200){
  108.     ms5=0; //5毫秒計(jì)數(shù)清零
  109.     add_time(); //時(shí)間步進(jìn)1秒
  110.     }
  111.    

  112. }
復(fù)制代碼



作者: lzxwsk    時(shí)間: 2016-9-29 06:06
很好...............51黑有你更精彩
作者: snln    時(shí)間: 2016-10-9 06:16
多長(zhǎng)時(shí)間誤差1秒??
作者: middfat    時(shí)間: 2016-10-9 16:06
是只用單片機(jī)內(nèi)部震蕩器實(shí)現(xiàn)嗎?
作者: HWL0541    時(shí)間: 2016-10-28 08:13
看看高到什么程度
作者: dzljp    時(shí)間: 2016-10-28 08:21
這個(gè)要學(xué)習(xí)學(xué)習(xí),謝謝樓主!
作者: tangquan    時(shí)間: 2016-10-28 09:08
誰(shuí)不是這么做的??這個(gè)的主要誤差來(lái)源晶振的精度,不過(guò)如果定時(shí)器沒(méi)有定時(shí)正確誤差也會(huì)很大
作者: westlife96    時(shí)間: 2016-10-29 23:15
我覺(jué)得目前高精度還是需要溫補(bǔ)晶振。如果是我的話,我會(huì)選擇1s的中斷
作者: 小白呂    時(shí)間: 2016-10-30 20:37
51hei有你更精彩
作者: 黃昭旨    時(shí)間: 2016-11-3 15:41
參考看看,希望能得到收穫
作者: 84533243    時(shí)間: 2016-11-3 18:29
很好,,,,
作者: 張偉靈    時(shí)間: 2016-11-3 21:23
真心謝謝樓主,謝謝
作者: xuguoying_cz    時(shí)間: 2016-11-3 23:19
如果是我的話,我會(huì)選擇1s的中斷
作者: npn    時(shí)間: 2016-11-4 08:25
xuguoying_cz 發(fā)表于 2016-11-3 23:19
如果是我的話,我會(huì)選擇1s的中斷

你覺(jué)得TH0和TL0計(jì)數(shù)器計(jì)滿需要1s時(shí)間?經(jīng)過(guò)計(jì)算晶振頻率要用32.768khz的,配置CLK_DIV寄存器為0x07即對(duì)系統(tǒng)時(shí)鐘128進(jìn)行分頻,所以需要4.194304Mhz的晶振,分頻后串口通訊的波特率最高1024bps,最后中斷里處理時(shí)間計(jì)數(shù)指令平均需要幾十毫秒。


作者: babyqq2x    時(shí)間: 2016-11-5 19:36
看看吧,反正也不懂
作者: xgm2t    時(shí)間: 2016-11-6 18:21
年誤差多少?

作者: fire_205    時(shí)間: 2016-11-6 18:44
這個(gè)是51單片機(jī)的程序嗎?還是兼容stm系列的
作者: davg1    時(shí)間: 2016-11-6 21:05
會(huì)有溫漂吧。
作者: npn    時(shí)間: 2016-11-6 21:53
fire_205 發(fā)表于 2016-11-6 18:44
這個(gè)是51單片機(jī)的程序嗎?還是兼容stm系列的

只針對(duì)51指令集系列而設(shè)計(jì)的,其他指令集的可能需要修改一些頭文件以及io口變量常量的定義聲明方法以及配置的定時(shí)器的寄存器和中斷觸發(fā)方法就行,其他的日期時(shí)間設(shè)置走時(shí)判斷語(yǔ)句大部分都不需要修改的。
作者: npn    時(shí)間: 2016-11-6 22:01
davg1 發(fā)表于 2016-11-6 21:05
會(huì)有溫漂吧。

若是溫漂對(duì)晶振頻率影響非常大的話,你覺(jué)得數(shù)顯掛鐘以及熱水器微波爐之類的設(shè)備在極端溫度下運(yùn)行,時(shí)間系統(tǒng)的誤差會(huì)有多大?但規(guī)定范圍內(nèi)溫漂對(duì)頻率的影響不超過(guò)一定值的晶振是合格的。

作者: npn    時(shí)間: 2016-11-6 22:12
xgm2t 發(fā)表于 2016-11-6 18:21
年誤差多少?

對(duì)于晶振的輕微溫漂以及老化的影響而產(chǎn)生誤差,通過(guò)gps/gsm/cdma模塊更正時(shí)間保證零誤差,還有長(zhǎng)波授時(shí)的方法原理如同收音機(jī),其中有bpc/jjy/wwvb/dcf/msf等,不同國(guó)家發(fā)射的協(xié)議以及覆蓋范圍發(fā)射時(shí)間都有不同,通常一個(gè)發(fā)射基站就能覆蓋上千公里,根據(jù)發(fā)射的編碼協(xié)議解碼后獲得時(shí)間寫入內(nèi)部時(shí)間系統(tǒng)走時(shí),通常幾小時(shí)或幾天更正一次時(shí)間,而授時(shí)信號(hào)發(fā)射站以及網(wǎng)絡(luò)授時(shí)服務(wù)器均采用原子鐘計(jì)時(shí),數(shù)億年誤差1秒,幾乎可以忽略不計(jì)。

作者: 1123212143255    時(shí)間: 2016-11-7 05:48
正想學(xué)習(xí)做一個(gè),看看必有收獲。
作者: yjx189    時(shí)間: 2016-11-7 06:28

是只用單片機(jī)內(nèi)部震蕩器實(shí)現(xiàn)嗎
作者: yjj8    時(shí)間: 2016-11-7 14:48
這個(gè)要看看。。。。。。。。。。
作者: yznj    時(shí)間: 2016-11-7 20:59
看看是什么好東東
作者: 15170220697    時(shí)間: 2016-11-8 09:56
啦啦啦啦啦啦啦啦啦啦啦
作者: 滴~電子小白    時(shí)間: 2016-11-8 11:20
回復(fù),看看學(xué)習(xí)一下
作者: chaojiceo    時(shí)間: 2016-11-8 15:40
多長(zhǎng)時(shí)間誤差1秒??
作者: stz0401    時(shí)間: 2016-11-8 19:06
很好,非常感謝
作者: qqqchen321    時(shí)間: 2016-11-8 21:52
看一下了,不錯(cuò)的程序
作者: liwenjiefa    時(shí)間: 2016-11-10 14:57
看看學(xué)學(xué)看看
作者: Skipper    時(shí)間: 2016-11-10 16:01
感謝樓主分享!!
作者: 南天白云    時(shí)間: 2016-11-10 16:06
有這么準(zhǔn)嗎
作者: sunlei058378    時(shí)間: 2016-11-10 19:45
難得時(shí)間計(jì)算的這么精確
作者: 羊男3    時(shí)間: 2016-11-11 14:07
來(lái)學(xué)習(xí)學(xué)習(xí)····
作者: valiantzhang    時(shí)間: 2016-11-12 12:33
學(xué)習(xí)學(xué)習(xí)
作者: 黑橙orangerx    時(shí)間: 2016-11-13 16:07
感謝分享,先看看
作者: 5083    時(shí)間: 2016-11-13 16:55
能不能自動(dòng)校對(duì)時(shí)間呢?
作者: npn    時(shí)間: 2016-11-13 17:42
5083 發(fā)表于 2016-11-13 16:55
能不能自動(dòng)校對(duì)時(shí)間呢?

校對(duì)時(shí)間數(shù)據(jù)需要模塊,獲取的時(shí)間用set_time();函數(shù)即可寫入。

作者: 5083    時(shí)間: 2016-11-13 19:21
npn 發(fā)表于 2016-11-13 17:42
校對(duì)時(shí)間數(shù)據(jù)需要模塊,獲取的時(shí)間用set_time();函數(shù)即可寫入。

什么模塊最好?加一個(gè)GPS模塊用來(lái)對(duì)時(shí)也不錯(cuò)
作者: 維超    時(shí)間: 2016-11-13 21:46
學(xué)習(xí)下樓主的高招
作者: kaka_kaka    時(shí)間: 2016-11-13 22:26
厲害,學(xué)習(xí)學(xué)習(xí)
作者: 1245812141    時(shí)間: 2016-11-14 09:11
感謝分享
作者: mark張    時(shí)間: 2016-11-14 10:05
贊一個(gè)。!
作者: djjzf    時(shí)間: 2016-11-14 11:49
學(xué)習(xí)一下, 不知道懂不懂
作者: lantian12310    時(shí)間: 2016-11-14 15:39
不錯(cuò)看看怎樣
作者: ymsg1983    時(shí)間: 2016-11-15 22:20
非常感謝
作者: ymsg1983    時(shí)間: 2016-11-15 22:20
太好了,謝謝
作者: a1184569302    時(shí)間: 2016-11-22 13:54
么么么么么么
作者: 程世龍    時(shí)間: 2016-11-22 22:15
我想用32和ds12b887做一個(gè)時(shí)鐘,借鑒借鑒程序
作者: xsynet    時(shí)間: 2016-11-23 08:18
我想看看,學(xué)習(xí)學(xué)習(xí),謝謝!
作者: xsynet    時(shí)間: 2016-11-23 08:23
時(shí)間這么精確,贊一個(gè)!
作者: Demonss    時(shí)間: 2016-11-23 12:57
用單片機(jī)制作最高精度時(shí)間系統(tǒng),可移植到任何時(shí)
作者: cj543464501    時(shí)間: 2016-11-23 16:00
感謝樓主分享
作者: 1007327969    時(shí)間: 2016-11-23 16:30
謝謝分享
作者: huluguojian    時(shí)間: 2016-11-23 23:10
進(jìn)來(lái)學(xué)習(xí)一下
作者: wuyibin2003    時(shí)間: 2016-11-27 18:58
不用晶振嗎
作者: 51hdzlt1    時(shí)間: 2016-11-30 11:37
看看 感謝樓主分享!
作者: 1027711848    時(shí)間: 2016-12-1 08:03
好的 看看啦 我也不知道
作者: mok3cdma    時(shí)間: 2016-12-1 22:00
來(lái)學(xué)習(xí)一下
作者: toman    時(shí)間: 2016-12-1 22:00
貌似新的單片機(jī)內(nèi)部都帶有時(shí)鐘的,新手路過(guò)勿噴!
作者: ssfc    時(shí)間: 2016-12-1 22:37
學(xué)習(xí),學(xué)習(xí)。。
作者: npn    時(shí)間: 2016-12-2 06:18
5083 發(fā)表于 2016-11-13 19:21
什么模塊最好?加一個(gè)GPS模塊用來(lái)對(duì)時(shí)也不錯(cuò)

任何的gps模塊都必須有這種功能的,里面還有很多定位參數(shù)。

作者: fengxqjack    時(shí)間: 2016-12-2 15:30
挺好的,下載了沒(méi)事可以做做
作者: hongshun325    時(shí)間: 2016-12-2 22:10
看看代碼效率如何
作者: xht9951    時(shí)間: 2016-12-3 09:06
感謝樓主,學(xué)習(xí)學(xué)習(xí),謝謝!~
作者: jcygh    時(shí)間: 2016-12-3 10:31
很給力!
贊一個(gè)!
作者: jcygh    時(shí)間: 2016-12-3 10:33
很給力!
贊一個(gè)!
作者: whty2010    時(shí)間: 2016-12-3 22:11
感謝樓主分享。
作者: 冥暝醉了    時(shí)間: 2016-12-5 09:34
很好.………
作者: jackhwang    時(shí)間: 2016-12-5 11:55
很好奇。
作者: 趕腳好流弊    時(shí)間: 2016-12-5 11:57
贊一個(gè),對(duì)我們新手很有幫助
作者: 趕腳好流弊    時(shí)間: 2016-12-5 11:57
贊一個(gè),對(duì)我們新手很有幫助
作者: 趕腳好流弊    時(shí)間: 2016-12-5 11:58
贊一個(gè),對(duì)我們新手很有幫助
作者: 匆匆歲月    時(shí)間: 2016-12-5 13:05
厲害厲害
作者: 九尾    時(shí)間: 2016-12-5 16:08
看看吧。。謝謝樓主
作者: wuyutuzhi    時(shí)間: 2016-12-5 17:30
bucuobucuo
作者: R0514    時(shí)間: 2016-12-5 19:17
謝謝樓主,
作者: 李振魂    時(shí)間: 2016-12-5 19:22
ganxie
作者: 猜猜我是誰(shuí)    時(shí)間: 2016-12-5 19:36
真是雪中送炭啊
作者: 15279046525    時(shí)間: 2016-12-6 10:38
完美。。。。。。。。。
作者: zrb5688    時(shí)間: 2016-12-6 21:48
謝謝樓主分享。
作者: 水水水水水水    時(shí)間: 2016-12-6 23:59
得目前高精度還是需要溫補(bǔ)晶振。如果是我的話,我會(huì)選擇1s的中斷
作者: a4732710    時(shí)間: 2016-12-7 07:18
這個(gè)好呀,就想要精確點(diǎn)的
作者: dhwuwe    時(shí)間: 2016-12-7 07:47
好好學(xué)習(xí)學(xué)習(xí)
作者: VECENT_LIN    時(shí)間: 2016-12-7 11:56
謝謝樓主分享!
作者: w854088557    時(shí)間: 2016-12-7 17:01
這個(gè)要學(xué)習(xí)一下
作者: Ro-mastar    時(shí)間: 2016-12-7 19:25
很好,謝謝
作者: 17190181898    時(shí)間: 2016-12-10 16:39
很好
作者: sdbzwhh    時(shí)間: 2016-12-10 19:44
專業(yè)單片機(jī)正要求做這個(gè)呢,謝謝了
作者: aa3222505    時(shí)間: 2016-12-10 21:12
參考參考
作者: 新手勿噴    時(shí)間: 2016-12-12 07:40
我想看看
作者: by64214    時(shí)間: 2016-12-12 20:34
謝謝分享   學(xué)學(xué)看看
作者: 明白    時(shí)間: 2016-12-12 21:28
肯定不是高精度,因?yàn)闆](méi)有同步補(bǔ)償
作者: npn    時(shí)間: 2016-12-13 07:26
明白 發(fā)表于 2016-12-12 21:28
肯定不是高精度,因?yàn)闆](méi)有同步補(bǔ)償

這當(dāng)然是只用1片單片機(jī)實(shí)現(xiàn)的最高精度,沒(méi)有任何模塊所實(shí)現(xiàn)的,精度由晶振決定,時(shí)間同步需要擴(kuò)展gps或網(wǎng)絡(luò)模塊。

作者: 1534545848    時(shí)間: 2016-12-13 19:45
感謝樓主分享!
作者: setst    時(shí)間: 2016-12-13 21:04
贊一個(gè)
作者: 油條大師    時(shí)間: 2016-12-14 07:37
O(∩_∩)O謝謝
作者: 張紀(jì)元    時(shí)間: 2016-12-14 09:02
不錯(cuò) 不錯(cuò)
作者: hhdsdy    時(shí)間: 2016-12-14 09:23
下載一個(gè)看看,謝謝了!




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1