嵌入式——定時器中斷

先上代碼算法

#include <reg52.h>

void Init();

void main(){
    Init();
}

void Init(){
    TMOD = 0x01;
    TH0 = 0x4b;
    TL0 = 0xfc;    //定時器時間50ms,針對11.0592MHz頻率CPU
    ET0 = 1;
    EA = 1;
    TR0 = 1;
}

void Timer0() interrupt 1 {
    TH0 = 0x4b;
    TL0 = 0xfd;
    //Timer循環體,運行過程放這裏
}

示例代碼就要有示例代碼的樣子,簡簡單單的才能把問題說清楚!函數

先解釋下幾個變量,TMOD,TH0,TL0,ET0,EA,TR0,這些變量不是我定義的,而是<reg52.h>頭文件中的,先掌握用法,再深究原理。學習

 

TMOD:選擇定時器的模式,不一樣的模式主要是能數到的最大數不一樣,通常就用模式1,最大可數到65535spa

TH0:TL0:設置起始值,TH0 故名思議就是數字轉爲16進制的高8位,TL0爲低八位code

TR0:啓動、中止定時器,1啓動,0中止,這個比較好理解吧blog

EA:容許系統進行中斷,1容許,0禁止,算是個權限之類的東西it

ET0:容許定時器0進行中斷,1容許,0禁止入門

 

到這裏你確定還會有疑問,我接着給你解釋!class

 

1.定時器定時時間怎麼算的啊,0x4bfc轉爲10進制並非50啊?變量

 

——確實不是50,在講定時器時間的算法以前,先得說下這個定時器的原理。

在咱們高級語言習慣中,定時器就是給他設定一個數,他一秒數一下,數到那個值後進行一次定時操做。可是在嵌入式中並非這樣,也是由於這樣錯誤的想法,我不理解了好久。

  在嵌入式中,定時器的實現原理是,他從某個數開始數,一直數到上限(如65535),到65536的時候定時器溢出,進行一次操做,而咱們給的0x4bfc是定時器的起始值,也就是說定時器將從這個值開始數,一直數到65535,中間所耗費的時間就是50ms。

 

2.彷佛明白了,那這個時間具體怎麼算啊?

 

——恩,這個問題稍有些複雜,回答這個問題以前,仍是要繼續引入幾個概念。

  時鐘週期T1:晶振振盪週期,公式  T1 = 1/頻率  ,如11.0592MHz的晶振頻率  T1 = 1/11.0592 us

  機器週期T2:機器執行一條基本指令的時間,公式  T2 = 12 * T1  ,如11.0592MHz的機器週期約爲  1.085 us

  

  因此,要定時50ms的計算過程

  50ms = 50000us = 50000/1.085 機器週期 = 46083 次

  也就是說,要讓計時器數 46083 次就行了,要數到65535,那麼很天然就知道是要從 65535 - 46083 = 19452 數起

  19452D = 0x4bfc

  因此 TH0 = 0x4b,  TL0 = 0xfc

 

3.我有注意到,TH0 TL0 TR0 ET0 後面都有0,感受挺奇怪的?

 

——你看的很仔細,沒錯,這個0是有意義的。事實上,單片機裏有兩個定時器,TH0表示第一個定時器,TH1表示第二個,另外幾個以T開頭的都表示定時器變量,也都有T_0和 T_1兩種,E開頭的表示與中斷相關。

 

4.interrupt 1 裏面的1是什麼意思,能換成其餘數字嗎?

——後面的1是中斷號,Timer0 這個函數名稱你能夠隨便取,可是後面這個數字倒是固定的,由於它是用來講明這個函數是誰的中斷函數,1表示是定時器1來中斷,3表示定時器2中斷。事實上,還有幾個額外的中斷類型,可是做爲入門,就不在這裏列舉了。

 

5.爲何在中斷函數 Timer0 裏又從新設置了一次 TH0 和 TL0 呢,這是必須的嗎?

 

——上面有提到過,這個函數裏面的過程是在定時器數到65536溢出後執行的,可是有個問題是溢出完後TH0 和 TL0就會被重置爲0,若是你不從新設定的話它會從0開始數起,因此是必須的,定時器1和定時器2都是這樣的。

 

定時器簡單的理解到這就差很少了,關於中斷還須要繼續學習,另外幾種中斷方式原理上都是有共通點的!

相關文章
相關標籤/搜索