有什么好法子較準它呢? 需要加大晶振旁邊的那兩個瓷片電容?還是減小呢? 程序上可有好的調(diào)校辦法呢? 謝謝!
不過,這樣能改到比如說一個月誤差只一秒或更少嗎? 程序上除了定時,有一些語句也占用了時間的啊.
那么單片機的水平是不是就可以說有了一個較大的提高了呢? 或者說也不過是剛剛起步而已. 我現(xiàn)在多是在網(wǎng)上下載程序來看,做試驗板試的.
一般都是在定時中斷里給個變量累加, 就把定時器初始值變小(中斷周期變大),變量累加值改小,即可!
我用8032做的電子鐘走了一個星期了,還是和電視上顯示的時間一致!沒加修正程序.倒是我家電子表差了好幾秒.
老x太出名了
如果是11.0592晶振的問題,那么必須修正!!! 相關(guān)鏈接:http://www.ednchina.com/blog/hotpower/13661/message.aspx
那么大的誤差肯定是程序問題,改電容是改不過來的
其實在查詢或中斷中只讀定時器誤差就完全取決你所用時鐘的誤差!用普通4M精度也不錯.
12/11.0592=1.085us. 最終導致了誤差的產(chǎn)生和累積. 程序里用的是模式1.(是LCD顯示的,網(wǎng)上下載的程序) 我以前做過一個(是LED顯示的,網(wǎng)上下載的程序),用的是12MHz的晶振,就很準的啊!!!
相關(guān)鏈接:http://shop35088126.taobao.com
我也是一個新手,我對單片機的研究也有一段時間了,可是也很難做到誤差很小啊。
PPM? 程序......?
是不是用這個11.0592MHz晶振的原因呢? 12/11.0592=1.085us. 最終導致了誤差的產(chǎn)生和累積. 程序里用的是模式1.(是LCD顯示的,網(wǎng)上下載的程序) 我以前做過一個(是LED顯示的,網(wǎng)上下載的程序),用的是12MHz的晶振,就很準的啊!!! 不對,用11.0592M的
晶體時鐘一樣很準,條件是必須是5的倍數(shù),看: //單片機執(zhí)行一條指令所需要的時鐘周期數(shù)(6或12) //在此使用的是
AT89C52芯片,每個機器周期=12*時鐘周期 #defineOSC_PER_INST(12) //晶體為11.0592M或22.1184M //#defineOSC_FREQ(11059200UL) #defineOSC_FREQ(22118400UL) //創(chuàng)建可移植的
硬件定時溢出 //此處定時溢出(TIMEROUT必須等于5或是5的倍數(shù)) #defineTIMEROUT(5)//單位是毫秒(最小基數(shù)是5) #definePRELOAD_mS(65536-(TIMEROUT*OSC_FREQ)/(OSC_PER_INST*1000)) //當晶體是11.0592M或是其倍數(shù)是,定時器低位自動裝載 #definePRELOAD_mS_H(PRELOAD_mS/256) 注意:要用定時器低位自動裝載或T2的高低位自動裝載.好像論壇上有一個貼就是討論時鐘誤差的問題的,上面的代碼我就是受到它的啟發(fā)定成的.關(guān)于定時器誤的問題.hotpower和所長都有說過,LZ存細找找看. 例: /*--------------------------------------------------------------------------------*- MAIN.H(V1.1) 項目頭文件(ProjectHeader) -*---------------------------------------------------------------------------------*/ /* *Copyright(c)2006,wsl于深圳xxxx硬件工程部 *Allrightsreserved * *文件名稱:main.h *文件標識:項目頭文件(ProjectHeader) *摘要:包含
控制器類型,
振蕩器的頻率,執(zhí)行一條指令 *所需要的振蕩器的周期數(shù),公共的數(shù)據(jù)類型, *及定義中斷向量值. * *當前版本:1.1*取代版本: *作者:*原作者:MichaelJ.Pont *完成日期:2006-09-14*完成日期: **********************************************************************************/ #ifndef_MAIM_H//防止main.h被重復(fù)引用 #define_MAIN_H /**********************************************************************************/ #include #include #ifndefNULL #defineNULL((void*)0L)/*Stdlib.handString.halreadyincludeNULL*/ #endif //--------------------------------------------------------------------------------- //每個項目都要修改這一段 //--------------------------------------------------------------------------------- //控制器類型 //#include"REG52.H" #include"STC12C5410AD.H" /**********************************************************************************/ //單片機執(zhí)行一條指令所需要的時鐘周期數(shù)(6或12) //在此使用的是AT89C52芯片,每個機器周期=12*時鐘周期 #defineOSC_PER_INST(12) //晶體為11.0592M或22.1184M //#defineOSC_FREQ(11059200UL) #defineOSC_FREQ(22118400UL) //創(chuàng)建可移植的硬件定時溢出 //此處定時溢出(TIMEROUT必須等于5或是5的倍數(shù)) #defineTIMEROUT(5)//單位是毫秒(最小基數(shù)是5) #definePRELOAD_mS(65536-(TIMEROUT*OSC_FREQ)/(OSC_PER_INST*1000)) //當晶體是11.0592M或是其倍數(shù)是,定時器低位自動裝載 #definePRELOAD_mS_H(PRELOAD_mS/256) /***************************************************************************************/ //--------------------------------------------------------- //以下部分不需要修改 //--------------------------------------------------------- //雜項宏定義 #ifndefTRUE #defineFALSE0 #defineTRUE(!FALSE) #endif #defineINT_EAEA #defineINT_ET2ET2 #defineINT_ESES #defineINT_ET1ET1 #defineINT_EX1EX1 #defineINT_ET0ET0 #defineINT_EX0EX0 #defineINTERRUPT_ENABLE()INT_EA=TRUE/*開總中斷標志位*/ #defineINTERRUPT_DISABLE()INT_EA=FALSE/*禁止所有中斷*/ #defineINTERRUPT_GET()INT_EA/*讀中斷*/ #defineINTERRUPT_SET(bit)INT_EA=(bit)/*設(shè)置中斷,即EA=0或1*/ #defineSETBIT(A,B)(A|=1<<(B))/*A=Register,B=Bitnumber(7..0)*/ #defineRESETBIT(A,B)(A&=~(1<<(B)))/*A=Register,B=Bitnumber(7..0)*/ #defineGETBIT(A,B)((A>>B)&0x01) #endif /*---------------------------------------------------------*- --------------------NEDOFFILE-------------------------- -*---------------------------------------------------------*/ /*--------------------------------------------------------------------*- SysTick.C(V1.00) 這里是系統(tǒng)的時標. -*---------------------------------------------------------------------*/ /* *Copyright(c)2007 *Allrightsreserved * *文件名稱:SysTick.C *文件標識: *摘要:系統(tǒng)的時標(20mS) * *當前版本:1.0*取代版本: *作者:*原作者: *完成日期:2007-07-31*完成日期: ************************************************************************/ #include"LCD_Dis.h" #include"SysTick.h" //串行口發(fā)送 unsignedcharTxd_Buffer[MAX_TRANSMIT_LENGTH]; unsignedchardataTxd_Counter;//串行口要發(fā)送的字節(jié)數(shù) bitSendit;//串口發(fā)送狀態(tài).0發(fā)送中,1發(fā)送完畢 unsignedcharG_speek=0; unsignedchardot=8; //私有函數(shù) staticvoidserial_transmit(unsignedchar*pBuffer,unsignedcharnumber,unsignedcharMaxLen); /*---------------------------------------------------------*- *函數(shù)名稱:T0_TICK_INIT() *入口:xx *出口:xx *函數(shù)功能:T0初始化 * *說明:為了時標的準確性,系統(tǒng)采用T0模式1,16位加載模式. *將T0的低位計數(shù)器設(shè)計為自動加載. * *當前版本:1.0*取代版本: *作者:*原作者: *完成日期:2007-07-31*完成日期: -*---------------------------------------------------------*/ voidT0_TICK_INIT(void) { TMOD&=0xf0; TMOD|=0x01; TL0=0; TH0=PRELOAD_mS_H; ET0=1; TR0=1; } /*---------------------------------------------------------*- *函數(shù)名稱:SystemTick() *函數(shù)功能:系統(tǒng)時標.任何任務(wù)執(zhí)行時間都不能大于系統(tǒng)時標. *說明:T0的低位計數(shù)器為自動加載.(系統(tǒng)時標為5mS) *當前版本:1.0*取代版本: *作者:*原作者: *完成日期:2007-07-31*完成日期: -*---------------------------------------------------------*/ voidSystemTick(void)interrupt1using1 { TH0=PRELOAD_mS_H; } 上面就是系統(tǒng)時標完整的代碼.看看對89cpu是否有用.
我現(xiàn)在在調(diào)那初始的定時賦值TL0.用模式1. 調(diào)了很多次,不過還是有1秒的誤差.還沒徹底調(diào)好.
呵呵!精益求精!
著重看看你填寫的定時器時間常數(shù),需要結(jié)合你使用的晶體,簡單
計算一下.如果是第一次編寫時鐘程序的話,1小時誤差1-2秒,屬于正常,可以根據(jù)的具體誤差進行微調(diào),當然,是在中斷程序里面
單片機差不多就只能到這種精確度了.大家再討論一下還有什么好的辦法沒有.
一、硬件方式: 晶振的匹配電容用可變電容,然后用頻率檢測頻率即可 二、軟硬件方式: CPU你做個頻率程序,檢測標準頻率源的頻率,然后記下來用于重載 三、純軟件方式: 先調(diào)好當前時間,按校準鍵先記下當前時間;等一段時間后必然會產(chǎn)生誤差,這時按二次調(diào)整鍵重新輸入時間,程序自動計算中間的偏差和實際走過的時間,就知道校準的比率了,把它存下來用于實際校準 自己根據(jù)儀器情況和是否有非易失存儲器來決定吧 個人制作的話我比較偏向于方案三. 呵呵^_^
修改那個定時的TL0,慢時就加大它,快了就減小它. 有效果!我用手機校時的,我的手機特準時!! 但是,現(xiàn)在,改到#39H,感覺差不多了: 若再加1,就會變快;若再減1,就會變慢; 可沒多久的時間后,還是有些誤差! 是不是需要微調(diào)一下晶體邊上的那兩個瓷片電容了呢? 那兩個瓷片電容,加大會變快還是變慢呢? 謝謝!
或者2的N次方倍率的,比如4.096Mhz
11025900=12×256×16×225,可以保證1秒重載時低12位不用動,也可以保證1/16秒重載時低8位不需動,這樣就是一個新手也不會產(chǎn)生重載時的軟件誤差; 而對于12M,每個指令周期1uS,這個對于人來說時方便,但對于機器來說卻是很不方便的數(shù)字。 跟重要的是11.0592MHz可以很簡單的獲得高的標準波特率,還可以把T2省出來 最后: 其實,只要設(shè)計者稍微花點心思,不管用多少的晶振,都可以做到軟件無累計誤差的,此時的“誤差”應(yīng)該叫錯誤才對。
任何CPU都必須在當前一條指令執(zhí)行完之后才能響應(yīng)中斷,51的指令可是1/2/3/4周期五花八門。沒準進中斷要延遲多少個周期! 所以,主程序就一句話“pcon|=1”休眠,從休眠進中斷的延遲是確定的。 當然,T2自裝載模式也可以解決問題
但是對于時鐘來說什么時候計數(shù)是沒關(guān)系的,只要把當前值加進去就能消除掉累計誤差的,選擇合適的晶振頻率更是可以徹底避免重載誤差。 因此沒必要非要主程序休眠,而且畢竟很多時候系統(tǒng)總得多多少少做些別的事,不可能只作時鐘 --要是只作時鐘,就算是傻子也能做到?jīng)]有累計誤差得:-) 當然,對于52,則使用T2的自動重載模式才是最方便的。
掐準了在讓他跑一個星期 不過就做個電子鐘用51也太浪費了吧 4位的單片機用32.768K振蕩就可以保證很穩(wěn)很準
硬件方面,競爭應(yīng)選用鐘表晶振32.768k,精度高、溫漂小(可參考晶振的器件手冊)。軟件對定時器設(shè)置初值設(shè)置應(yīng)準確,設(shè)置可采用網(wǎng)上一些初值設(shè)置
工具(懶人51等)。
要用32768的
可以自己做的玩玩,但這種東西只能在實驗室里與要求不高的場合使用.當然你不考慮成本采用帶溫補的晶振是有可能的.現(xiàn)在有些供電公司裝的分時電能表,各廠家都是用硬件時鐘(
R8025)做的,但不做溫度補償也做不到0.5s/d的
貴嗎?好像沒見過.
換帶副振的芯片,用32.768的晶振,可以做到幾乎沒誤差~
最開始不太懂修正,做出來的時鐘誤差應(yīng)該應(yīng)該說很離譜。 至于現(xiàn)在做時鐘一般是用32768的晶振吧,但是大家有沒有去仔細的注意那個頻率呢?是否用
示波器測過其晶振波形呢? 前段時間做了個時鐘類的小產(chǎn)品,能過不同的電容,調(diào)晶振的頻率都精確到32.7680KHZ,所做的實驗表明,用22pf電容最合適(25的也可以)。而我在現(xiàn)在做的一個ARM項目中,時鐘要求不嚴格,用的30pf電容,我隨便一測,頻率為 32.75x(不太記得是不是這么多,也可能是32.765x),可見其精度相差甚遠。對于一般的要求也不用太在意,但如果是真正的時鐘,還是得多花些時間多測一下。不然做出的產(chǎn)品絕對不合格。
用單片機編譯器的跑表啊, 什么11.0592.什么12M都行.怎么加語句都行. 你跑表以后可以看到一個中斷差多少,再該中斷的定時.(11.0592改不到很準,建議用12M的,但是調(diào)節(jié)后怎么不會3小時差一秒.)應(yīng)該會一個月差幾秒了. 還有就是晶振的質(zhì)量要好,最好選那種長一點的.那種會穩(wěn)定些.
"但是,現(xiàn)在,改到#39H,感覺差不多了: 若再加1,就會變快;若再減1,就會變慢;" 這個很難解決. 精度要那么高,還是用"4位的單片機用32.768K振蕩就可以保證很穩(wěn)很準"---37樓. 手表的晶振就是32.768Khz的.
下面內(nèi)容是在保證晶體準確度的情況下而進行的探討: 首先:11059200=144*64*100*12,其中12為機器周期和指令周期的關(guān)系。100是為了保持準確度取的10ms為單位,1秒的次數(shù),當然,也可以取100ms為單位,那么該次數(shù)就為10.前面那個144是8位自動裝載的值,這個值盡量大,這樣可以少一些中斷次數(shù),有些可以使用16位的自動裝載,那么問題就非常簡單了。64這個數(shù)字就不用太解釋了。 假設(shè)T0自動裝載的值為144,裝載后每次進入一個中斷,中斷的任務(wù)是CNT_T0加一 那么 if(++Cnt_t0==64) { Cnt_10ms++;//表示10ms計數(shù)加一 Cnt_t0=0; } //64次自動裝載后,總的時間為10ms。這個只要保證T0的優(yōu)先級,保證T0自動裝載的時候,一定會發(fā)生中斷就可以。至于是否馬上或等待幾個周期后進入,這個是沒有關(guān)系的。 主程序中,就使用CNT_10ms就可以了。我不管在什么時候使用CNT_10ms,本程序不會產(chǎn)生累計誤差的。實際我們平時要求沒有太高,顯示問題可以早幾個ms,晚幾個ms.但是視覺上是沒有多大的變化的。同時又能夠保證定時的準確度。 個人不太同意使用軟件補償?shù)姆椒▉碜觥.吘寡a償?shù)姆椒ㄊ遣豢煽康摹?這個方法我本人是經(jīng)過測試過的。每天系統(tǒng)的誤差在3秒以內(nèi)。這個3秒還是晶體的溫度變化引起的。 希望對你有點兒用處。
144周期就中斷一次,中斷太過于頻繁了 再就是,“軟件補償?shù)姆椒ā焙捅苊獾臀恢剌d的方法完全可以做到無累計誤差的,根本就不存在什么“不可靠”,做的不對那也是你的問題。 至于時鐘校準的3種方案,看我30樓的貼吧 估計沒人仔細看過...
11059200=144*64*100*12=256*36*100*12 這樣做行不?
11059200=2^14*3^3*5^2 51或別的單片機都可以很容易的獲得標準波特率和能被256整除的重載值。 比如10mS、5mS、2.5mS、10/3mS的整數(shù)倍的定時時間,而這些定時值低位都不需要重載!
可以減少定時中斷程序里的命令行,轉(zhuǎn)移到主程序中。
用什么頻率的晶振不是問題。。。
現(xiàn)在已經(jīng)很明確了,可以完全消除軟件引入的誤差,下一步該討論晶體的精度了. 消費電子中做電子鐘的晶體大部分都用32.768KHz,4.19304MHz,它們的精度通常是多少PPM的? 我們51所用的12MHz,11.0592MHz通常又是多少PPM的?
都是新手,就幾個建議供參考: 1.首先程序要對 2.頻率最好能整除 3.晶振精度要高,我想摟主用的晶體精度不會超過20ppm。你自己可以計算一下一年能有幾分鐘的誤差。
已徹底解決
我搞過,和計算機的時間還看不出積累誤差. 通過T2自動重裝定時,
原則上,用MCU的定時器實現(xiàn)軟件RTC,最好選擇有自動重加載功能定時器的MCU
用模擬IIC的,可以學者玩玩
可以想辦法換成12Mhz的晶振,也可以設(shè)計程序來改善哈。
通過其它計算修正時間,而不能修改TH/TL的值
我認為是程序問題。程序中的一些語句要占用一些時間,在設(shè)置定時中斷初值時要考慮這個問題。 把晶陣換成12MHz或6MHz,這樣便于計算機器周期。
我也是用11.0592的晶振,請問中斷服務(wù)程序應(yīng)該不會占時間吧。 在重新裝載常數(shù)時把定時器關(guān)了,裝完再開管用嗎?
12M的不可以嗎
下面鏈接如果搞明白了,就會知道為什么手表晶振是32.768KHz 51用11.0592MHz的人很多,幾乎占80%(俺保守的估計) 明白了俺在解答~~~ 一直看這個貼子在增高,真搞不明白樓主的程序是怎么編寫的~~~ 相關(guān)鏈接:http://blog.ednchina.com/hotpower/13661/message.aspx
11.0592晶振是沒有錯的,理論上不會有偏差的,但是器件與理論模型是有差距的,所以最好用時鐘測試儀測試偏差,然后修正兩個起振電容,可以達到目的(但依然有偏差,不過很小)。
我的問題: "晶振旁邊的那兩個瓷片電容增大或者是減小對時鐘快慢有何影響呢?" 我沒試過.理論上該是怎么講呢? 若把那兩個瓷片電容增大些,時鐘會變快還是會變慢呢? hotpower,您好!讓您見笑了! 那個程序是從網(wǎng)上下載的一個時鐘程序. 我焊完板弄好單片機插上,時鐘不準,是慢了; 后來我就調(diào)那個TLO了,是有效果啊! 把TLO調(diào)到某一個數(shù)時,好像是#3AH,就差不多了,但還是不準。 這時再加大TLO,如改成#3BH,就會又快1秒。 這時再減小TLO,如改成#39H,就會又慢1秒。 感謝大家的解答。
首先是晶振的正確選擇. 在51中,由于一般為12分頻,當然現(xiàn)在還有6分頻和1分頻(不分頻)的. 為什么在嚴格定時里,如1秒,...1分種...1小時等不能用12的倍數(shù)呢???? 實際我在。。。 先到這里~~~俺倒塌STM32首次成功,趕寫作文...
我經(jīng)常用2051做一些簡單的設(shè)備,程序框架都是固定的。 用T0做個1/N秒的時標,大部分的任務(wù)的時序都根據(jù)1/N秒的整數(shù)倍來運行,也附加個時間顯示功能。12M、11.0592M、3.6864、6M的這幾種晶體我在完全相同的程序上(用什么晶體就只改了一下FOSC定義)用過,幾天內(nèi)都幾乎沒有誤差。 我是這樣做的: #defineFOSC11.0592 #defineMACHINE_NUM12 #defineTICKS_PER_SEC50 #defineT0_RELOAD(uint16)(-FOSC*1000000/TICKS_PER_SEC/MACHINE_NUM) 在T0中斷服務(wù)程序返回前做如下處理: TR0=0; abc=(uint16)(T0_RELOAD+15)+(TL0|(TH0<<8)); TL0=(uint8)abc; TH0=(uint8)(abc>>8); TR0=1; 上面“T0_RELOAD+15”中的15是上述代碼(用Keil編譯)運行的時間,假如用匯編的話效率更高,比15要小。 xwj說得很對,11.0592M是個很好用的頻率,它可以做一秒的分頻數(shù)很靈活(20、30、40、50、60、80、90等都可以在程序上不會有絲毫誤差),而12M就不能做30、60之類的分頻。
雖然晶振和電容會對誤差有影響,那也應(yīng)該是1天才會快慢幾秒鐘。 你這個不僅要考慮定時器的初始化,還要考慮指令的時鐘周期。
如果你是用定時器做的話 那么應(yīng)該是初值設(shè)置的問題應(yīng)該用11.0592mhz來準確計算
老帖子被翻出來了 又學到了很多
軟件累積誤差很容易就可以做到 0.01ppm 以下,而且還可以以 0.01ppm 為單位微調(diào)計時快慢(這個功能 用于校準硬件誤差)。 說軟件做不到的人,是他還沒找到方法。 有人說硬件誤差都有 10ppm 了,軟件累積誤差沒必要做到 0.01ppm,確實是這樣,但有些人連 100ppm 的軟件微調(diào)都做不到,這就顯現(xiàn)出這個方法的價值了。
直接用1302時鐘芯片啊 那家伙的誤差可小多了啊
1:不是所有的晶體都適合做時鐘的,32.768K是最好的 2:晶體一般采用三點式電容振蕩電路,就是單片機的那種,這個時候晶體等價為電感 3:32.768K附近的晶體,等效的電感的Q值最大,對外界的抗干擾能力最強 4:大家可以這么理解,晶體頻率從0到無窮大,肯定有一個性能最好的Q值晶體頻率,而這個頻率就在32K附近,其他都是比這個頻點差的。這是簡單的數(shù)學思維 5:在11.0592MHz,就算它的精度達到10ppm,但抗干擾穩(wěn)定性,還是非常差的,Q值很低,這沒有任何意義的,頻率再往上,Q值更低,振蕩都更加難,不是說頻率可以無限制的增長的。 以上都在不考慮軟件問題的情況下提的,若你的軟件就有問題,沒什么可談的。 創(chuàng)易電子 www.designeasy.com.cn
誤差是可以減小的
理解透徹就該用32768的晶體了。
我做過,一天就差1秒左右。3分鐘1秒這個程序肯定有問題
18樓的回答是一種非常大的可能,再有可能就是定時器沒有用自動重載功能,程序沒有計算進入中斷的時間。 用11.0592的晶振分頻需要是27的整數(shù)倍 做個廣告,去看俺寫的《刪繁就簡》吧,里面有答案
既然知道誤差率,在程序里修正不就行了嘛,這個有什么好說的
這樣的問題一般是軟件引起的 最好嵌入?yún)R編。
用定時器定時方式二,9216次是10ms,就可以精確s了,TL0,TH0均賦初值為00H,這樣256*36=9216 精確10ms 再100次就精確1s
這墳挖了又挖
這墳挖的好,我來撿幾個古董。
看你什么單片機51的話還是12M吧 1US