51單片機(jī)之寄存器-3.1單片機(jī)定時(shí)器
講定時(shí)器之前我們來(lái)看看如何操作鬧鐘,這個(gè)生活中的小例子,相信大家都很熟悉。首先我們要設(shè)定定時(shí)時(shí)間,定時(shí)多久呢?我們通過(guò)調(diào)節(jié)如圖中紅色區(qū)域指針來(lái)告訴鬧鐘定時(shí)多久。然后開(kāi)啟鬧鐘,怎么樣開(kāi)啟呢?如上圖中藍(lán)色部分,按下按鈕讓鬧鐘知道現(xiàn)在要開(kāi)啟定時(shí)的功能了。很簡(jiǎn)單的兩個(gè)動(dòng)作,鬧鐘設(shè)置就完成了。之后就是鬧鐘自己的事情了。你就可以去干別的事情了,比如看電影,睡覺(jué),喝茶等等。那么定時(shí)的時(shí)間到了怎么樣告訴你呢?大家都知道,通過(guò)響鈴來(lái)告訴你時(shí)間到了。懂得了鬧鐘的過(guò)程,那么類比一下就很容易明白單片機(jī)定時(shí)器。前面講過(guò),單片機(jī)是人設(shè)計(jì)的產(chǎn)品,自然反映人的思維過(guò)程。只不過(guò)在單片機(jī)中,它把日常用的詞匯專業(yè)化了,功能復(fù)雜了一點(diǎn)?,F(xiàn)在我們來(lái)按照鬧鐘的思維講述單片機(jī)定時(shí)器。
本文引用地址:http://m.butianyuan.cn/article/201611/319546.htm首先我們看看如何開(kāi)啟定時(shí)器,在鬧鐘中我們使用手來(lái)按下按鈕,這樣鬧鐘定時(shí)就開(kāi)啟了。在單片機(jī)中只有0和1,那么很容易想到采用0和1控制定時(shí)的開(kāi)關(guān),并給它取個(gè)名字(TR0). 如何理解這個(gè)名字了,T表示timer, R表示run,0表示定時(shí)器,合起來(lái)就表示定時(shí)器0運(yùn)行控制,這樣很容易就記住了定時(shí)器的開(kāi)關(guān)控制。那么下一個(gè)問(wèn)題,定時(shí)多長(zhǎng)時(shí)間。講這個(gè)問(wèn)題之前我們先來(lái)看看鬧鐘如何計(jì)時(shí)的。秒鐘每走一格就是1s,走10格我們就知道走了10s,也就是說(shuō)我們可以通過(guò)查看格子的數(shù)目來(lái)知道時(shí)間的量。在單片機(jī)中如何計(jì)時(shí)呢?如上圖,有兩個(gè)寄存器TH0和TL0,很容易想到,可以用TH0和TL0中存放的數(shù)據(jù)來(lái)知道時(shí)間。鬧鐘中每一個(gè)格子是1秒鐘,那么在TH0和TL0中每放一個(gè)數(shù)是多少時(shí)間呢。定時(shí)器計(jì)時(shí)是通過(guò)晶振來(lái)完成的。這里我們使用的晶振大小為11.0592M,表示一秒鐘時(shí)間內(nèi),晶振運(yùn)行11.0592次,那么運(yùn)行一次的時(shí)間為[1/(11.0592M)]S, TH0和TL0中每計(jì)數(shù)一次需要晶振運(yùn)行12次(至于為什么,后面我們會(huì)講到),因此需要的時(shí)間為12×[1/(11.0592M)]S. 為了方便計(jì)算我們把它換成微秒單位: (12/11.0592)Us. 可見(jiàn)時(shí)間長(zhǎng)度是通過(guò)TH0和TL0來(lái)完成的。那么能不能只用一個(gè)TL0來(lái)計(jì)數(shù)呢?當(dāng)然可以。因此這里就涉及到了計(jì)時(shí)模式的問(wèn)題,TH0+TL0構(gòu)成16bit的計(jì)時(shí)器,或者只使用TL0或者使用TH0(8bit)和TL0低5位。那么我用TH0高4位和TL0低7位可不可以?不可以,我們不去追問(wèn)為什么,單片機(jī)工程師設(shè)計(jì)的,我們要做的就是了解它的規(guī)則。既然工作模式有這么多,那么單片機(jī)怎么知道要使用哪種工作模式。很明顯需要有個(gè)寄存器來(lái)告訴單片機(jī)這個(gè)信息,這個(gè)寄存器叫TMOD. 如上圖所示的M0和M1,很容易知道2個(gè)位就能產(chǎn)生4種組合情況(00/01/10/11),這樣分別對(duì)應(yīng)與定時(shí)器的4種工作模式。最后一個(gè)問(wèn)題,到點(diǎn)響鈴。鬧鐘定時(shí)到了會(huì)發(fā)出響鈴來(lái)通知你,那么在單片機(jī)中到點(diǎn)了會(huì)通知CPU,怎么通知呢,如上圖所示中的TF0(F-full表示滿了,也就是溢出), TH0/TL0滿了TF0就會(huì)由0變1,然后通過(guò)硬件通知CPU時(shí)間到了。這樣就完成了整個(gè)定時(shí)過(guò)程。從以上分析可以看出,定時(shí)器的操作過(guò)程與鬧鐘非常相似,只不過(guò)單片機(jī)的定時(shí)器在計(jì)數(shù)方面復(fù)雜了一點(diǎn),多了幾種工作模式?,F(xiàn)在相信大家已經(jīng)大概了解單片機(jī)定時(shí)器了。
?現(xiàn)在我們根據(jù)所講的內(nèi)容,舉一個(gè)簡(jiǎn)單例子,通過(guò)定時(shí)器0來(lái)控制LED亮一秒滅一秒。按照上面過(guò)程,我們一步一步來(lái)分析
(1) 確定定時(shí)多長(zhǎng)時(shí)間
前面講了定時(shí)時(shí)間是通過(guò)TH0和TL0來(lái)控制的,那么使用TH0和TL0之前先要設(shè)定工作模式,用16bit還是8bit或者其他。這里我們選擇16bit。怎么選呢?表1中給出了定時(shí)器0和1工作模式的控制寄存器,8個(gè)位的初始化值都是0,綠色部分用來(lái)控制定時(shí)器1,黃色部分用來(lái)控制定時(shí)器0,現(xiàn)在我們只看黃色部分。一共4個(gè)控制位,Gate,C/T,M1,M0. 很容易看到,Gate,C/T都要設(shè)置0,現(xiàn)在要選中16bit的工作模式,那么M1M0=01. 因此TMOD=00000001=0X01 假設(shè)在圖2中,TL0,TH0初始值為0,那么16bit最多可以裝下65535,考慮到溢出,因此這里取65536,每裝一個(gè)數(shù)需要(12/11.0592)Us,那么裝65536需要,UnitT=65536×(12/11.0592)約等于71000Us,也就是71ms. 現(xiàn)在我要定時(shí)1s,很明顯,TH0和TL0不夠用,那是不是要多增加幾個(gè)TH0和TL0,沒(méi)有必要。我們可以通過(guò)軟件來(lái)解決硬件上的不足,最簡(jiǎn)單的方式就是使用循環(huán)多次。比如我讓UnitT為10ms,那么循環(huán)100次就是1秒了。那么怎么設(shè)置UnitT=10000Us, UnitT=(65536-X) × (12/11.0592)=10000Us, 其中X為TH0和TL0組成的16bit的初始值。將這個(gè)等式改進(jìn)一下:
UnitT=(65536-X) / 0.9216, 在該式中UnitT×0.9216要小于65536,并且要保證UnitT×0.9216為正整數(shù),因此UnitT的取值范圍為:
10000
因此簡(jiǎn)單來(lái)看,UnitT可以取10ms, 20ms, 30ms, 40ms, 50ms, 60ms, 70ms,
再根據(jù)我們最終要定時(shí)的時(shí)間為1000ms, 因此UnitT只能取10ms, 20ms, 50ms,這樣根據(jù)UnitT=(65536-X) / 0.9216就能計(jì)算出初始值X,
這里我們?nèi)nitT=50ms, X=19456,16進(jìn)制表示為: 4C00H, 因此TH0= 0X4C, THL0=0X00.
因此這樣我們就確定了定時(shí)時(shí)間用的初始值,TH0和TL0,并且需要重復(fù)20次
(2) 啟動(dòng)定時(shí)器
如何啟動(dòng)定時(shí)器,查看表2定時(shí)器控制寄存器TCON,只要設(shè)置TR0=1即可。表2中涉及到中斷的問(wèn)題我們暫時(shí)不管,這里我們只討論定時(shí)器,下一講談中斷。這里為什么能直接設(shè)置TR0,為什么在設(shè)置定時(shí)器工作模式時(shí)不能直接設(shè)置M1M0,而要通過(guò)TMOD來(lái)設(shè)置。這個(gè)涉及到尋址方式的問(wèn)題,我們暫時(shí)不討論。
(3) 響鈴?fù)ㄖ?/p>
那么鬧鐘響鈴對(duì)應(yīng)定時(shí)器的哪個(gè)部分。前面我們?cè)O(shè)置了TH0和TL0,初始值為19456,然后不停的增大直到65535,再增大一個(gè)變成65536此時(shí)TH0和TL0裝不下了,因此溢出,此時(shí)單片機(jī)通過(guò)硬件將TF0從0變?yōu)?來(lái)通知CPU,查看表2中TF0的說(shuō)明可知。因此TF0的值對(duì)應(yīng)著響鈴。
(4) 點(diǎn)亮LED
我們要讓LED延時(shí)1s后點(diǎn)亮或者熄滅,因此這里需要一個(gè)參數(shù)來(lái)對(duì)定時(shí)器TF0的溢出次數(shù)計(jì)數(shù),當(dāng)溢出20次時(shí),表示定時(shí)到了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;
}
}
}
}
}
評(píng)論