8051定時器/計數(shù)器介紹:
8051有兩個定時器/計數(shù)器,而8052則有三個定時器/計數(shù)器。定時器、計數(shù)器本質(zhì)都是一樣的,定時器通過對內(nèi)部脈沖進行計數(shù)來達到計時的目的,而計數(shù)器是對外部輸入脈沖進行計數(shù),所以它們的本質(zhì)都是一樣的。
定時器/計數(shù)器的工作模式:
定時器/計數(shù)器0有四種工作模式,而定時器/計數(shù)器1只有三種工作模式,工作模式由TMOD寄存器的M1和M0位控制。
M1M0工作模式00013位定時器/計數(shù)器。01116位定時器/計數(shù)器。1028位自動重裝定時器/計數(shù)器。113模式3只能用于定時器/計數(shù)器0,T0被分為兩個8位定時器/計數(shù)器,TL0可以作為定時器/計數(shù)器來使用,由T0的控制位來控制,而TH0只能用于計數(shù)器,有T1的控制位來控制。GATEGATE為0時,由TRx(軟件控制)來控制定時器/計數(shù)器的啟動和停止,當GATE為1時,定時器/計數(shù)器的啟動由TRx和引腳INTx共同來控制(硬件來控制,僅當TRx=1并且引腳INTx輸入高電平時才工作)。C/T定時器/計數(shù)器選擇位,0工作在定時器模式,1工作在計數(shù)器模式。TCON寄存器:TFx定時器/計數(shù)器溢出標志位,當定時器/計數(shù)器計數(shù)溢出時,由硬件自動置1,在編寫程序時可以通過檢測該位來判斷是否達到定時時間,需要通過軟件來清零。工作在中斷方式下不需要清零,因為在執(zhí)行中斷服務(wù)程序時會自動給我們清零。TRx定時器/計數(shù)器運行控制位。IE寄存器:ETx定時器/計數(shù)器中斷使能位。EA全局中斷使能位。
THx、TLx初值計算:
假設(shè)8051外接12MHz的晶振,由于8051的機器周期是時鐘周期的12分頻,所以8051的機器周期為1MHz,那么計數(shù)一次的時間剛好為1us,如果定時器工作在模式0下,那么可以最長計時為8192us,工作模式1可以最長計時為65536us。那么假設(shè)8051工作在模式1下,定時1ms,那么THx、TLx的初值應(yīng)該為多少呢?如果定時1ms,也就意味著需要計數(shù)1000次,那么初值就應(yīng)該為65536-1000=64536,也就是THx=0xFC,TLx=0x18。
根據(jù)上面可以總結(jié)出如下公式:
定時時間=(最大計數(shù)值-計數(shù)器初值)*機器周期=(最大計數(shù)值-計數(shù)器初值)*(12000000/晶振頻率(Hz))(us);
計數(shù)器初值=(最大計數(shù)值-定時時間*(晶振頻率(Hz)/12000000));
套用這個公式,初值=(65536-1000*(12000000/12000000))=64536=0xFC18,那么TH就應(yīng)該為0xFC,TL為0x18。
整個程序如下:
/*timer.c*/
#include
#defineOSC_FREQ12000000UL
#defineTIMER_MODE00x00
#defineTIMER_MODE10x01
#defineTIMER_MODE20x02
#defineTIMER_MODE30x03
voidtimer0_init(void)
{
TMOD&=0xF0;
TMOD|=TIMER_MODE1;/*Timer0workon16-bittimermode*/
TH0=(65536-1000*(OSC_FREQ/12000000))>>8;
TL0=(65536-1000*(OSC_FREQ/12000000))&0x00FF;
TR0=1;/*Turnontimer0*/
}
voiddelayms(unsignedintn)
{
while(n--){
while(!TF0);
TF0=0;
TH0=(65536-1000*(OSC_FREQ/12000000))>>8;
TL0=(65536-1000*(OSC_FREQ/12000000))&0x00FF;
}
}
/*timer.h*/
#ifndef__TIMER_H
#define__TIMER_H
externvoidtimer0_init(void);
externvoiddelayms(unsignedintn);
#endif/*__TIMER_H*/
/*main.c*/
#include
#include"timer.h"
#defineled1P2_0
voidmain(void)
{
timer0_init();
while(1){
led1=0;
delayms(1000);
led1=1;
delayms(1000);
}
}