Re: [問題] 89S51 使用 C51 計時問題

作者: deo2000 (800IM)   2014-06-08 05:55:04
※ 引述《a45601236qq (Ming)》之銘言:
: C_CPP 板問 51 相關問題的人好像比較少,所以就來這邊借問了...
: 今天試著做一下模擬 ms 計算的(高階語言 sleep 都喜歡以 1ms * n 為單位)
: 試著計時 60 秒後,發現每分鐘都會誤差五秒鐘(感覺有點大)
60秒誤差一秒都嫌太大
: 想請大家幫忙看一下是否有問題...
: 感謝<_ _)
: #include <AT89X51.h>
: int Timer1Ms = 0; //1ms * n
: int Timer1Value = 0;
時脈沒寫, 那我就假設最一般的case, 輸入給timer的週期 = 1us
: void main()
: {
: TMOD = 0x10; //7-2 tmod
: TL0 = ( 8192 - 5000 ) % 32;
: TH0 = ( 8192 - 5000 ) / 32;
: TL1 = ( 65536 - 1000 ) % 256;
: TH1 = ( 65536 - 1000 ) / 256;
這裡看起來是因為要以 ms 為單位, 需要計數超過 256 所以用 mode1,
但是中斷要去 reload 就影響計時準確度,
我的作法是改用 mode2, 數到 200個pulse*1us=200us,
在中斷累積50次overflow時, 秒數++
: Timer1Value = 60000;
: Timer1Ms = Timer1Value;
: //TR0 = 1;
: TR1 = 1;
: EA = 1; ET0 = 1; ET1 = 1; //6-3 IE
: while (1) ;
: }
: void timer1_isr() interrupt 3
: {
: TL1 = ( 65536 - 1000 ) % 256;
: TH1 = ( 65536 - 1000 ) / 256;
如果這邊硬是要用mode1, 那也有一些作法可以提高計時準確性
1. 在 main 就先算出 TH1 TL1 的常數值(也許compiler已經幫你做)
2. reload 前先TR1=0,reload後TR1=1,
因為只要 TR1==1 的情況下
reload 過程中 Timer1 依然在計數, TH1 TL1 依然在累加,沒停過
: Timer1Ms -= 1;
3.如果 main 沒有在跑 UART 或 LCD 什麼的跑得夠快的話, 以下這幾行可以留到main去做
: if (Timer1Ms == 0)
: {
: Timer1Ms = Timer1Value;
: P1_2 = ~(P1_2);
: }
: }

Links booklink

Contact Us: admin [ a t ] ucptt.com