定時器(一)

使用單片機(jī)時,編程會高頻率用到延時,如led燈閃爍,蜂鳴器長短鳴,秒表應(yīng)用等等。首先考慮軟件延時,但這個時間不精確,占用硬件資源。使用延時函數(shù)是,其他函數(shù)不能運行。這個方案cut掉。硬件延時,嗯,誤差非常小。但成本較高,且參數(shù)調(diào)節(jié)不便。這個也不行。選擇采用定時器調(diào)節(jié)時間,不占用cpu時間,能與CPU并行工作,實現(xiàn)精確的定時和計數(shù)。又可以通過編程設(shè)置其他工作方式和其他參數(shù),因此使用非常方便。下面介紹定時器的使用。

概述

定時器系統(tǒng)是單片機(jī)內(nèi)部一個獨立的硬件部分,它與cpu和晶振通過內(nèi)部某些控制線連接并相互作用,cpu一旦設(shè)置開啟定時功能后,定時器便在晶振的作用下自動計時,但定時器的計數(shù)器計滿后,會產(chǎn)生中斷。計數(shù)時間一次為12/晶振頻率。在晶振頻率為11.0595mhz時,計數(shù)一次時間約等于1.09us。
89c52單片機(jī)定時器系統(tǒng)有三個定時器/計數(shù)器,分別是定時器T0,定時器T1,T2定時器。他們既有定時器功能,也有計數(shù)器功能。T0,T1有四種工作方式,T2有三種工作模式。

內(nèi)部結(jié)構(gòu)

定時器結(jié)構(gòu)

由上圖可知,定時器系統(tǒng)有兩個寄存器組成,分別是TCON,TMOD。還可看出tcon控制外部中斷,tmod控制定時器工作方式。tmod寄存器分為兩部分,高四位為t1定時器控制位,低四位為t0定時器控制位。t0定時器與th0,tl0兩個8位計數(shù)器有關(guān),。t1定時器與th1,tl1兩個8位計數(shù)器有關(guān)。上圖信息就這么多,接下來看看兩個寄存器相關(guān)數(shù)據(jù)。

寄存器TCON

寄存器TCON

TF1:定時器 1 溢出標(biāo)志。當(dāng)定時器/計數(shù)器 1 溢出時,由 硬件置位;當(dāng)主機(jī)響應(yīng)中斷,
轉(zhuǎn)向中斷服務(wù)程序時,由硬件清零。
TR1:定時器 1 運行控制位, 由軟件置位/ 復(fù)位來開啟或關(guān)閉定時器/計數(shù)器 1。
TF0:定時器 0 溢出標(biāo)志。當(dāng)定時器/計數(shù)器 0 溢出時,由 硬件置位;當(dāng)主機(jī)響應(yīng)中斷,
轉(zhuǎn)向中斷服務(wù)程序時,由硬件清零。
TR0:定時器 0 運行控制位,由 軟件置位/ 復(fù)位來開啟或關(guān)閉定時器/計數(shù)器 0。
IE1:外部中斷 1 跳變中斷請求標(biāo)志,當(dāng)檢測到 INT1 發(fā)生 1 到 0 的跳變時,由硬件置位;當(dāng)主機(jī)響應(yīng)中斷, 轉(zhuǎn)向中斷服務(wù)程序時,由硬件清零。
IT1:外部中斷 1 觸發(fā)方式控制位,由 軟件置位或清零來選擇外部中斷 1 的跳變/電平觸發(fā)中斷請求。IT1=0 時,外部中斷 1 為電平觸發(fā)方式,當(dāng) INT1 輸入低電平時,置位 IE1。
采用電平觸發(fā)方式時,外部中斷源必須保持低電平有效,直到該中斷被 CPU 響應(yīng),同時在該中斷服務(wù)程序執(zhí)行完之前,外部中斷源必須被清除,否則將產(chǎn)生另一次中斷。IT1=1 時,外部中斷 1 為邊沿觸發(fā)方式,在對 INT1 的相鄰兩次采樣中,如果一個周期中為高電平,接下來的周期為低電平,則置位 IE1,表示外部中斷 1 正在向 CPU 申請中斷。直到該中斷被CPU 響應(yīng)時,才被 硬件清零。
IE0:外部中斷 0 跳變中斷請求標(biāo)志,當(dāng)檢測到 INT1 發(fā)生 1 到 0 的跳變時,由硬件置位;當(dāng)主機(jī)響應(yīng)中斷, 轉(zhuǎn)向中斷服務(wù)程序時,由硬件清零。
IT0:外部中斷 0 觸發(fā)方式控制位,應(yīng)用同 IT1。

這個寄存器與中斷有關(guān),支持位尋址,就是可以對其每一位進(jìn)行單獨操作。定時器工作就是在一個特定的間隔(與晶振有關(guān))加1,等到加到定時器溢滿時,會觸發(fā)外部中斷。這兩個定時器都是16位可編程定時器/計數(shù)器。最大可裝2的16次方。,就是65535.,定時器在晶振為11.0592MHZ時,間隔約等于1.09us。
(關(guān)于中斷的知識在上一篇文章有詳細(xì)介紹,在這里就不累贅。)

寄存器TMOD

寄存器TMOD

GATE:門控制位,當(dāng) GATEx=1 時,控制寄存器 TCON 的 TRx=1(x=0 或 1)。當(dāng) GATEx=0 時,定時器啟動與停止僅受寄存器中的TRx來控制(x=0 或 1)。
C / :定時器、計數(shù)器方式選擇位,該位為 1 時為計數(shù)器,為 0 時為定時器。
M0:定時器/計數(shù)器工作模式選擇位。
M1:定時器/計數(shù)器工作模式選擇位。
注:高四位是T1定時器控制位,低四位是T0定時器控制位

工作方式如下圖所示

4種工作方式

這個寄存器是控制定時器的工作方式與哪個定時器工作。tmod寄存器支持位尋址,編程時只可以是總線式,不可以單個控制。因為兩個定時器命名一樣,單個控制會弄混。下面示范寫法:
TMOD=0X01; // 0000 0001
可以看出只有最低位為1,即T0定時器的M0=1;對照上圖數(shù)據(jù)可知,這是使用T0定時器的定時功能中的工作方式1,就是16位定時器。
TMOD=0X20; //0010 0000
這個看數(shù)據(jù)手冊得知是T1定時器的定時功能中的工作方式2,即具有自動重載的8位定時器。

附:定時器使用需要用到中斷,這里將中斷的中斷源優(yōu)先級放在下面。


中斷源優(yōu)先級

定時器使用

中斷函數(shù)

在介紹定時器使用時,先介紹中斷函數(shù),C51的中斷格式如下
void 函數(shù)名()iinterrupt 工作組
{
中斷內(nèi)容;
}
中斷函數(shù)不能返回值,所以前綴為void,函數(shù)名可以任意取,但一般建議使用有意義的名字,到時候檢查也可以明白是什么函數(shù),interrupt是c語言中的一個關(guān)鍵字--中斷,記住就行。工作組就是對應(yīng)中斷源,比如說,使用T1定時器,那中斷源就是定時器1中斷,這時工作組就是3。下面示范:
void timer_t1() interrupt 3
{
TH1=(0XE0);
TL1=(0X07);
}
上面這個實例很容易理解,對著手冊看就知道是T1定時器中斷。

定時器初值計算

中斷函數(shù)明白后,如何定時還是不清楚。開啟定時器后,定時器就會開始計數(shù),每次加1的間隔是固定的,而且到達(dá)最大值就會溢出,觸發(fā)中斷。這樣子的話我們可以設(shè)定一個初值,初值到最大值的時間假設(shè)為50ms,那樣的話定是的效果就達(dá)到了。定時器加1時間間隔約等于1.09us,定時器在沒有賦值時默認(rèn)初值為0,最大值為65535,計算可得655351.09us約等于72ms,沒有賦初值一次定時最大為72ms??梢栽O(shè)置一個初值,就拿50ms來說,501000/1.09約等于45872,也就是說經(jīng)過45872次計數(shù)時間為50ms,那初值就是65535-45872=19663。

大概了解定時器,來看看如何使用,定時器是由16位可編程寄存器組成,分為高8位,即THX(X=1或X=0)低8位TLX(X=1或X=0)。為了更好定時,肯定會選擇賦初值。這里介紹一種簡單的方法,不用計算。既然它們分為兩部分,可以利用這一特點。舉個例子:
選擇10ms時間,T1定時器。這里以晶振為12MHZ為準(zhǔn),因為11.0592MHZ計算麻煩,這樣計數(shù)一次就是1us;
TH1=(65535-10000)/256;//表示初值為55535,/256表示高8位的初值,很好理解,低 8位最多存2的8次方=256個數(shù),每滿一次高8位加1, /256表示高8位加了多少次。

TL1=(65535-10000)%256;// %256表示不滿256最后留下的數(shù)。

使用步驟

計算知道后,來看看定時器使用步驟:

  1. 對TMOD賦值,確定T0和T1的工作方式
  2. 計算初值,賦值TH0,TL0或TH1,TH1
  3. 對IE賦值,啟動中斷
  4. TR0或TR1置位,啟動定時器
  5. 處理中斷函數(shù),定時器中斷后變成默認(rèn)值0,要重新賦初值

例程

#inlclude<reg52.h>   //頭文件
sbit led=P1^1;   //位定義
unsigned char count; // 定義計數(shù)次數(shù)變量
mian()  //主函數(shù)
{
    
    TMOD=0X01;   //設(shè)置定時器T0 定時器功能 工作模式1
    TH0=(65536-50000)/256;     //賦初值   50ms
    TL0=(65536-50000)%256;
    EA=1;   //打開總中斷
    ET0=1;  //開定時器0中斷
    TR0=1;  //啟動定時器 
}
void timer_t0() intterrupt 1
{
    TH0=(65536-50000)/256;    //重新賦值
    TL0=(65536-50000)%256;
    count++;     //每中斷一次加1
    if(count==20)  //count==20時,說明1秒到
    {
        count=0;  //count清零,重新等待1秒的到來
        led=~led;   //led狀態(tài)取反
    }
}

上面注釋已經(jīng)很清楚,按照步驟來,一步一步設(shè)置參數(shù),基本不會出錯。在中斷函數(shù)中設(shè)置一個標(biāo)志位,中斷變化,變化成何值時,再狀態(tài)變化?;揪褪沁@個套路。給個建議,中斷函數(shù)不要寫太多東西,不然會出錯。試想一下,假如進(jìn)入中斷需5ms,但在中斷函數(shù)中命令要運行10ms,命令沒有運行完,又進(jìn)入中斷,就會出錯。

總結(jié)

定時器就這樣子,不會很難,一些命令在數(shù)據(jù)手冊都有,忘記了就重新看一下,寫多了就會記住·,重要的是記住步驟,記住編程思想,在寫之前在腦中想一下步驟,或在紙上把思路畫一下,那里不通就會躍然于紙上,再稍加思索一般就行了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容