新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 51單片機之寄存器-3.1單片機定時器

51單片機之寄存器-3.1單片機定時器

作者: 時間:2016-11-21 來源:網絡 收藏
前面我們講解了如何通過軟件來延時,從而達到了提升了燈亮與滅的間隔時間,其過程是讓cpu干別的事情,從而達到延時的效果。但是軟件延時不是很精確,這里我們學習一種比較精確的硬件延時,也叫定時器。定時器怎么理解呢?這里舉個簡單的例子來說明。
圖1 鬧鐘的操作?

講定時器之前我們來看看如何操作鬧鐘,這個生活中的小例子,相信大家都很熟悉。首先我們要設定定時時間,定時多久呢?我們通過調節(jié)如圖中紅色區(qū)域指針來告訴鬧鐘定時多久。然后開啟鬧鐘,怎么樣開啟呢?如上圖中藍色部分,按下按鈕讓鬧鐘知道現(xiàn)在要開啟定時的功能了。很簡單的兩個動作,鬧鐘設置就完成了。之后就是鬧鐘自己的事情了。你就可以去干別的事情了,比如看電影,睡覺,喝茶等等。那么定時的時間到了怎么樣告訴你呢?大家都知道,通過響鈴來告訴你時間到了。懂得了鬧鐘的過程,那么類比一下就很容易明白單片機定時器。前面講過,單片機是人設計的產品,自然反映人的思維過程。只不過在單片機中,它把日常用的詞匯專業(yè)化了,功能復雜了一點?,F(xiàn)在我們來按照鬧鐘的思維講述單片機定時器。

本文引用地址:http://butianyuan.cn/article/201611/319546.htm
圖2 定時器的操作示意圖?

首先我們看看如何開啟定時器,在鬧鐘中我們使用手來按下按鈕,這樣鬧鐘定時就開啟了。在單片機中只有0和1,那么很容易想到采用0和1控制定時的開關,并給它取個名字(TR0). 如何理解這個名字了,T表示timer, R表示run,0表示定時器,合起來就表示定時器0運行控制,這樣很容易就記住了定時器的開關控制。那么下一個問題,定時多長時間。講這個問題之前我們先來看看鬧鐘如何計時的。秒鐘每走一格就是1s,走10格我們就知道走了10s,也就是說我們可以通過查看格子的數(shù)目來知道時間的量。在單片機中如何計時呢?如上圖,有兩個寄存器TH0和TL0,很容易想到,可以用TH0和TL0中存放的數(shù)據(jù)來知道時間。鬧鐘中每一個格子是1秒鐘,那么在TH0和TL0中每放一個數(shù)是多少時間呢。定時器計時是通過晶振來完成的。這里我們使用的晶振大小為11.0592M,表示一秒鐘時間內,晶振運行11.0592次,那么運行一次的時間為[1/(11.0592M)]S, TH0和TL0中每計數(shù)一次需要晶振運行12次(至于為什么,后面我們會講到),因此需要的時間為12×[1/(11.0592M)]S. 為了方便計算我們把它換成微秒單位: (12/11.0592)Us. 可見時間長度是通過TH0和TL0來完成的。那么能不能只用一個TL0來計數(shù)呢?當然可以。因此這里就涉及到了計時模式的問題,TH0+TL0構成16bit的計時器,或者只使用TL0或者使用TH0(8bit)和TL0低5位。那么我用TH0高4位和TL0低7位可不可以?不可以,我們不去追問為什么,單片機工程師設計的,我們要做的就是了解它的規(guī)則。既然工作模式有這么多,那么單片機怎么知道要使用哪種工作模式。很明顯需要有個寄存器來告訴單片機這個信息,這個寄存器叫TMOD. 如上圖所示的M0和M1,很容易知道2個位就能產生4種組合情況(00/01/10/11),這樣分別對應與定時器的4種工作模式。最后一個問題,到點響鈴。鬧鐘定時到了會發(fā)出響鈴來通知你,那么在單片機中到點了會通知CPU,怎么通知呢,如上圖所示中的TF0(F-full表示滿了,也就是溢出), TH0/TL0滿了TF0就會由0變1,然后通過硬件通知CPU時間到了。這樣就完成了整個定時過程。從以上分析可以看出,定時器的操作過程與鬧鐘非常相似,只不過單片機的定時器在計數(shù)方面復雜了一點,多了幾種工作模式。現(xiàn)在相信大家已經大概了解單片機定時器了。

?現(xiàn)在我們根據(jù)所講的內容,舉一個簡單例子,通過定時器0來控制LED亮一秒滅一秒。按照上面過程,我們一步一步來分析

(1) 確定定時多長時間

前面講了定時時間是通過TH0和TL0來控制的,那么使用TH0和TL0之前先要設定工作模式,用16bit還是8bit或者其他。這里我們選擇16bit。怎么選呢?表1中給出了定時器0和1工作模式的控制寄存器,8個位的初始化值都是0,綠色部分用來控制定時器1,黃色部分用來控制定時器0,現(xiàn)在我們只看黃色部分。一共4個控制位,Gate,C/T,M1,M0. 很容易看到,Gate,C/T都要設置0,現(xiàn)在要選中16bit的工作模式,那么M1M0=01. 因此TMOD=00000001=0X01 假設在圖2中,TL0,TH0初始值為0,那么16bit最多可以裝下65535,考慮到溢出,因此這里取65536,每裝一個數(shù)需要(12/11.0592)Us,那么裝65536需要,UnitT=65536×(12/11.0592)約等于71000Us,也就是71ms. 現(xiàn)在我要定時1s,很明顯,TH0和TL0不夠用,那是不是要多增加幾個TH0和TL0,沒有必要。我們可以通過軟件來解決硬件上的不足,最簡單的方式就是使用循環(huán)多次。比如我讓UnitT為10ms,那么循環(huán)100次就是1秒了。那么怎么設置UnitT=10000Us, UnitT=(65536-X) × (12/11.0592)=10000Us, 其中X為TH0和TL0組成的16bit的初始值。將這個等式改進一下:

UnitT=(65536-X) / 0.9216, 在該式中UnitT×0.9216要小于65536,并且要保證UnitT×0.9216為正整數(shù),因此UnitT的取值范圍為:

10000

因此簡單來看,UnitT可以取10ms, 20ms, 30ms, 40ms, 50ms, 60ms, 70ms,

再根據(jù)我們最終要定時的時間為1000ms, 因此UnitT只能取10ms, 20ms, 50ms,這樣根據(jù)UnitT=(65536-X) / 0.9216就能計算出初始值X,

這里我們取UnitT=50ms, X=19456,16進制表示為: 4C00H, 因此TH0= 0X4C, THL0=0X00.

因此這樣我們就確定了定時時間用的初始值,TH0和TL0,并且需要重復20次

(2) 啟動定時器

如何啟動定時器,查看表2定時器控制寄存器TCON,只要設置TR0=1即可。表2中涉及到中斷的問題我們暫時不管,這里我們只討論定時器,下一講談中斷。這里為什么能直接設置TR0,為什么在設置定時器工作模式時不能直接設置M1M0,而要通過TMOD來設置。這個涉及到尋址方式的問題,我們暫時不討論。

(3) 響鈴通知

那么鬧鐘響鈴對應定時器的哪個部分。前面我們設置了TH0和TL0,初始值為19456,然后不停的增大直到65535,再增大一個變成65536此時TH0和TL0裝不下了,因此溢出,此時單片機通過硬件將TF0從0變?yōu)?來通知CPU,查看表2中TF0的說明可知。因此TF0的值對應著響鈴。

(4) 點亮LED

我們要讓LED延時1s后點亮或者熄滅,因此這里需要一個參數(shù)來對定時器TF0的溢出次數(shù)計數(shù),當溢出20次時,表示定時到了1s。

這樣我們很容易的得出程序的框架圖,

參考代碼如下:

#include "reg52.h"

sbit LED=P1^0;

void main(void)

{

unsigned char CYC = 0;

TMOD=0X01;

TH0=0X4C;

TL0=0X00;

TR0=1;

while(1)

{

if (TF0==1)

{

TF0=0;

TH0=0X4C;

TL0=0X00;

CYC++;

if(CYC==20)

{

CYC=0;

if(LED==0)

{

P1=0XFF ;

LED=1;

}

else

{

LED=0;

P1=0X00;

}

}

}

}

}



評論


技術專區(qū)

關閉