先看原理:89c51單片機內部有兩個16位的定時/計數器,即定時器T0和定時器T1,單片機的定時功能其實就是通過計數來實現的,當單片機每一個機器周期產生一個脈沖時,計數器就加一。
舉例說明:一個16位的定時器,它所能計數的范圍是0~65535,如果單片機采用的是12M的晶振,那么定時器單次最長的時間為65535*((1/12)*12),因為一個一個機器周期等于12個振蕩周期,那么定時器加一所用的時間是1/12M*12是1us,也就是一個12MHz晶振的51單片機單次最長時間約為65ms.
定時器如何控制
89c51的定時器由兩個寄存器控制,分別是工作模式寄存器TMOD和控制寄存器TCON
工作模式寄存器TMOD是用于控制定時器0/1的工作模式,通過對TMOD進行賦值,則可以改變定時器的工作模式
具體各位的定義如下,看圖
當我們使用定時器功能時,就只用設置D0、D1、D4、D5的的值就可以了,其余位置0即可
我們在使用定時器時基本使用的是模式1和模式2,模式0與模式3基本不用,我就不進行描述了。
模式1
當TMOD的D5位置0,D4位置1時,即為定時器T1的模式一,該模式對應的是一個16位的定時器,寄存器TH1和TL1即為T1初值的高8位和低8位,定時時間為:(65536-T1的初值)*振蕩周期*12
模式二
當TMOD的D5位置1,D4位置0時,即為定時器T1的模式二,該模式對應的是一個可以自動裝載的8位定時器,當定時器計數滿了(計數溢出時),會自動把TH1中的內容重新裝載到TL1中,那么模式二計數的最長時間即為(257-T1的初值)*振蕩周期*12
定時器的控制寄存器TCON
TCON的各位定義如下,看圖
TF1:T1的溢出標志位,當T1溢出時,由硬件自動使TF1位置1,并向CPU申請中斷。當CPU響應中斷進入中斷服務子程序后,TF1又被硬件自動清0,也可以用軟件清0.
TF0:T0溢出標志位。其功能和操作情況同TF1
TR1:T1的運行控制位,當該位置1時,即啟動定時器1當該位置0時,即關閉
TR0:T0的運行控制位,其功能及操作情況同TR1。
接下來我將用定時器來結合數碼管制作一個0-9計時器
代碼我給貼出來,供大家參考:
# include <reg52.h> //引用了51單片機的官方庫文件
void T0INI() ;
unsigned int temp = 0,i = 0; //中間變量
unsigned char leddata[]={
0xC0, //"0"
0xF9, //"1"
0xA4, //"2"
0xB0, //"3"
0x99, //"4"
0x92, //"5"
0x82, //"6"
0xF8, //"7"
0x80, //"8"
0x90, //"9"
0x88, //"A"
0x83, //"B"
0xC6, //"C"
0xA1, //"D"
0x86, //"E"
0x8E, //"F"
0x89, //"H"
0xC7, //"L"
0xC8, //"n"
0xC1, //"u"
0x8C, //"P"
0xA3, //"o"
0xBF, //"-"
0xFF, //熄滅
0xFF //自定義
};
void main()
{
T0INI();
while(1)
{
P2 = 0x0e; //位選段P20置0
P0 = leddata[i];
if(TF0 == 1)
{
TH0 = 0X3c;
TL0 = 0xb0; //12Mhz定時50ms
temp++;
}
if(temp == 20)
i++;
if(i == 10)
i = 0;
}
}
void T0INI() //定時器T0初始化
{
EA = 1; //cpu開總中斷
TCON = 0x10; //打開定時器T0
TMOD = 0x01; //設置T0為工作模式1,16位定時計數器
TH0 = 0X3c;
TL0 = 0xb0; //12Mhz定時50ms
}