標題: 單片機中斷定時為什么會晚? [打印本頁]

作者: 殿堂之上    時間: 2023-11-6 14:40
標題: 單片機中斷定時為什么會晚?
11.0592的晶振定時10ms不是沒有誤差嗎,為什么寫的鐘表一天會慢幾分鐘,是因為中斷程序運行時間過久,中斷時間到了前一個中斷還未出去而延遲嗎
單片機源程序如下:
#include <reg52.h>
#include <intrins.h>
#define Fosc 11.0592 //晶振頻率
#define FTime 10000  //中斷定時以us計
void main(void)
{
while(1);
}
void T0_Init(void)
{
        TMOD|=0x01;
        EA=1;
        ET0=1;
        TR0=1;
        TH0=(65536-FTime*Fosc/12)/256;
        TL0=(char)(65536-FTime*Fosc/12)%256;
}
void T0_Timer(void) interrupt 1
{
        TH0=(65536-FTime*Fosc/12)/256;
        TL0=(char)(65536-FTime*Fosc/12)%256;
}



作者: chxelc    時間: 2023-11-6 16:13
單片機精度沒那么高,精度要求高的時鐘應用,用專門的時鐘芯片如DS1302,PCF8563,DS3231等。
作者: Hephaestus    時間: 2023-11-6 16:24
chxelc 發(fā)表于 2023-11-6 16:13
單片機精度沒那么高,精度要求高的時鐘應用,用專門的時鐘芯片如DS1302,PCF8563,DS3231等。

單片機內(nèi)部RC振蕩器穩(wěn)定性不行,但是11MHz AT-cut quartz精度要比DS1302、PCF8563用的fork quartz好太多了,這些RTC芯片優(yōu)點在于功耗低,掉電依然可以用電池來運行,他們的精度根本不行,在高頻晶體面前就是個笑話。樓主如果用的是高頻晶體,可以修改軟件。當然DS3231屬于TCXO,精度最高。
作者: gongnn    時間: 2023-11-6 16:27
11.0592晶體做定時器生成1ms沒有誤差?記錯了吧,那是做串口波特率沒有誤差,你用12M晶體試試吧?
作者: wulin    時間: 2023-11-6 17:15
這種時鐘想要提高精度需要采取一點措施。改換12M或24M高品質晶振,定時器采用自動重裝模式,定時中斷周期盡可能短,建議不超過100uS。添加修正系數(shù)補償誤差。采取以上措施后可以將日誤差控制在1秒左右。
作者: 殿堂之上    時間: 2023-11-6 23:13
gongnn 發(fā)表于 2023-11-6 16:27
11.0592晶體做定時器生成1ms沒有誤差?記錯了吧,那是做串口波特率沒有誤差,你用12M晶體試試吧?

10ms寫錯了,程序里是10000us
作者: devcang    時間: 2023-11-7 09:51

DS3231 還可以,只是比較貴
作者: 18680365301    時間: 2023-11-29 11:51
晶振誤差多少,中斷跳轉,定時時間重載這些考慮進去沒
作者: npn    時間: 2023-11-29 13:20
仿真誤差大是程序有問題,實物誤差與晶振精度有關,定時器要設置成自動重載模式。
作者: 鵜鶘    時間: 2023-11-29 14:47
這是中斷模式1的工作機理引起的——從中斷申請的發(fā)出,到CPU響應,再到計算賦值完畢(主要是向TL賦值完畢),這是有時間的,這段時間遠不為0,每個中斷都插入了這樣一段時間所以就慢了,這絕不是精度問題,因為1天要慢好幾分鐘的。尤其是你在中斷程序里還進行了計算,這也很消耗時間,并且還把對TL的賦值放在了TH后,更增加了延時。解決這一問題的常規(guī)手法是在對TL賦值前讀出它的值,加在新值上賦給TL,并再加上2-5個修正值(可由實驗確定),因為賦值也要消耗時間的并且C是怎么編譯的我們也不知道。另一個更好的辦法是,調(diào)整中斷周期,使TL=0,這樣在中斷程序中可以不給TL賦值,只給TH賦值,使得計數(shù)不間斷,類似于中斷模式2,也就沒有了延時的產(chǎn)生。11.0592的晶振可以直接做到這點的,比如TH=180(即B4H),在中斷程序中刪掉TL的賦值語句,這樣的中斷計20次就是1秒。12兆的晶體做不到這點——算術問題,當然非要這么做也可以,增加了程序的復雜性。
作者: 鵜鶘    時間: 2023-11-29 15:02
實際上你的這個程序已經(jīng)滿足了上貼的條件,即TL=0,所以在中斷程序中直接刪除賦值語句【TL0=(char)(65536-FTime*Fosc/12)%256;】即可,其他哪里都不用變,這個幾分鐘的誤差即可徹底消除,非常簡單的事。再有的誤差那就是元器件的精度引起的了,遠不會超過1秒/天。那些說什么時鐘芯片的,都是想當然。
作者: npn    時間: 2023-11-29 15:02
鵜鶘 發(fā)表于 2023-11-29 14:47
這是中斷模式1的工作機理引起的——從中斷申請的發(fā)出,到CPU響應,再到計算賦值完畢(主要是向TL賦值完畢) ...

定時器設置為自動重載初值模式,這段時間就為0,你設置10ms的定時器,定時器中斷內(nèi)停留不得超過10ms
作者: ydatou    時間: 2023-11-29 17:20
void T0_Timer(void) interrupt 1
{
        TH0=(65536-FTime*Fosc/12)/256;
        //TL0=(char)(65536-FTime*Fosc/12)%256;
}

代碼改成這樣能顯著提高走時精度。樓主這行畫蛇添足。
在早期沒有自動重裝模式的單片機,想要走時準確,只能使用類似11.0592的晶振,這樣TL0的重裝值為0,也算間接實現(xiàn)了自動重裝。




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