第七章 定時器與計數器🇨🇳
AT89S52單片機片內集成有3個定時器/計數器T0、T1和T2
7.1定時器/計數器T0與T1的結構😃
一、 AT89S51定時器/計數器結構
-
T0、T1都有定時器和計數器兩種工作模式,實質都是對脈沖信號進行計數。
-
計數器模式是對加在T0(P3.4)和T1(P3.5)兩個引腳上的外部脈沖進行計數(見上圖);
-
定時器模式是對單片機的系統時鍾信號經片內12分頻后的內部脈沖信號(機器周期)計數,即每個機器周期使寄存器的值加1,屬於增1計數器,即每計一個脈沖,計數器增1。
-
定時器可看做是對機器周期的計數器,定時計數頻率是振盪頻率的1/12。
-
定時時間:可根據對內部脈沖信號的計數值可計算出定時時間。
定時時間 t =計數值N * Tcy -
計數器的起始計數都是從計數器的初值開始。AT89S52單片機復位時計數器的初值為0,也可用指令給計數器裝入一個新的初值,從新的初值開始計數。定時器/計數器屬於增1計數器。
-
設定計數次數:計數器的計數量程-計數初值
二、 T0、T1的4種工作方式(方式0、1、2和3)
- TMOD--選擇定時器/計數器T0、T1的工作模式和工作方式。
- TCON--控制T0、T1的啟動和停止計數,同時包含了T0、T1狀態。
三、 工作方式控制寄存器TMOD
TMOD用於選擇定時器/計數器的工作模式和工作方式,字節地址為89H,不能位尋址
8位分兩組,高4位控制T1,低4位控制T0。
-
各位的說明
(1)GATE—門控位
- GATE=0,K=TRx·INTx定時器是否計數,僅由控制位TRx(x = 0,1)來控制運行。
- GATE=1,K=TRx定時器是否運行,由外中斷引腳INTx* 上的電平與運行控制位TRx共同控制。
GATE=1時,“與門”的輸出信號K由INTx輸入電平和TRx位的狀態一起決定(即此時K=TRx·INTx),當且僅當TRx=1,INTx=1(高電平)時,計數啟動;否則,計數停止。
當INT0引腳為高電平時且TR0置位,TR0=1;啟動定時器T0;
當INT1引腳為高電平時且TR1置位,TR1=1;啟動定時器T1。
GATE=0時,“或門”輸出恆為1,“與門”的輸出信號K由TRx決定(即此時K=TRx),定時器不受INTx輸入電平的影響,由TRx直接控制定時器的啟動和停止。(2)M1、M0—工作方式選擇位
M1、M0的4種編碼,對應於4種工作方式的選擇
(3)C/T* —計數器模式和定時器模式選擇位
- C/T*=0, 定時器模式,對系統時鍾12分頻后的脈沖進行計數。
- C/T*=1, 計數器模式,計數器對外部輸入引腳T0(P3.4)或T1(P3.5)的外部脈沖(負跳變)計數。
四、定時器/計數器控制寄存器 TCON Timer Control Register
TCON字節地址88H,可位尋址,位地址為88H~8FH。
-
各位說明
(1)TF1、TF0—計數溢出標志位.
- 當計數器計數溢出時,該位置“1”。
- 使用查詢方式時,此位可供CPU查詢,但應注意查詢后,用軟件及時將該位清“0”。
- 使用中斷方式時,作為中斷請求標志位,進入中斷服務程序后由硬件自動清“0”。
(2)TR1、TR0—計數運行控制位
- TR1位(或TR0)=1,為啟動定時器/計數器工作的必要條件。
- TR1位(或TR0)=0,停止定時器/計數器工作。
- 該位可由軟件置“1”或清“0”。
7.2 定時器/計數器的4種工作方式
- 工作模式:決定定時器或者計數器
- 工作方式:決定計數范圍
一。方式0
當M1、M0=00,設置為方式0
-
方式0為13位計數器,由TLx(x = 0,1)的低5位和THx的高8位構成。TLx低5位溢出則向THx進位,THx計數溢出則把TCON中的溢出標志位TFx置“1”。
-
C/T*位控制電子開關決定2種工作模式。
-
GATE位狀態決定定時器/計數器運行控制是取決於TRx一個條件,還是取決於TRx和INTx*引腳狀態兩個條件。
二、方式1
當M1、M0=01時,工作於方式1
- 方式1和方式0差別僅僅在於計數器的位數不同,方式1為16位計數器,由THx高8位和TLx低8位構成(x = 0,1);
- 方式0則為13位計數器,有關控制狀態位含義(GATE、C/T* 、TFx、TRx)與方式0相同。
三、方式2
方式0和方式1最大特點是計數溢出后,計數器為全0。因此在循環定時或循環計數應用時就存在用指令反復裝入計數初值的問題,這會影響定時精度,方式2就是為解決此問題而設置的。
當M1、M0=10時,工作方式2
- 工作方式2為自動恢復初值(初值自動裝入)的8位定時器/計數器;
- TLx(x=0,1)作為常數緩沖器,當TLx計數溢出時,在溢出標志TFx置“1”的同時,還自動將THx中的初值送至TLx,使TLx從初值開始重新計數。
- 方式2適合於用作較精確的脈沖信號發生器
- 方式2可省去用戶軟件中重裝初值的指令執行時間,簡化定時初值的計算方法,可相當精確地定時。
四、方式3(T0)
- 方式3是為基本型8051單片機增加一個附加的8位定時器/計數器而設置的,從而使AT89S51具有3個定時器/計數器。
- 方式3只適用於T0,T1不能工作在方式3。
- T1方式3時相當於TR1 = 0,停止計數(此時T1可作為串口波特率產生器)。
-
工作方式3下的T0
TH0被固定作為一個8位定時器(不能作為外部計數模式)並使用定時器T1的狀態控制位TR1,同時占用定時器T1的中斷請求源TF1。
TL0使用T0的狀態控制位C/T* 、GATE、TR0
-
T0工作在方式3時,T1的各種工作方式
- 一般情況下,當T1用作串口波特率發生器時,T0才工作在方式3。
- T0方式3時,T1可為方式0、1、2,作為串口波特率發生器,或不需要中斷的場合。
(1)T1工作在方式0
- T1的控制字中M1、M0 = 00時,T1工作在方式0
(2)T1工作在方式1
- 當T1的控制字中M1、M0 = 01時,T1工作在方式1
(3)T1工作在方式2
- 當T1控制字中M1、M0 = 10時,T1為方式2
(4)T1設置在方式3
- T0方式3時,再把T1也設置成方式3,此時T1停止計數。
7.3計數器模式對外部輸入的計數信號的要求
-
當定時器/計數器T0與T1工作在計數器模式時,計數脈沖來自外部輸入引腳T0或T1。
-
當輸入信號產生負跳變時,計數值增1。
-
每個機器周期S5P2期間,都對外部輸入引腳T0或T1進行采樣。
-
如在第1個機器周期中采得值為1,而在下一個機器周期中采得的值為0,則在緊跟着的再下一個機器周期S3P1期間,計數器加1。
-
由於確認一次負跳變要花2個機器周期,即24個振盪周期,因此外部輸入的計數脈沖的最高頻率為系統振盪器頻率1/24。
也就是 最高頻率=系統振盪器頻率 / 24
-
如選用6MHz晶體,允許輸入脈沖頻率最高為250kHz。如選用12MHz頻率晶體,則可輸入最高頻率500kHz外部脈沖。
-
對外輸入信號占空比沒有限制,但為確保某一給定電平在變化前能被采樣1次,則該電平至少保持1個機器周期。
-
故對外部輸入信號要求見圖7-12,圖中Tcy為機器周期。
注意:定時器/計數器的初始化
一、初始化步驟
- 根據要求先給定時器方式寄存器TMOD送一個方式控制字,以設定定時器/計數器的相應工作方式。
- 根據實際需要給定時器/計數器選送定時器初值或計數器初值,以確定需要定時的時間和需要計數的初值。
- 根據需要給中斷允許寄存器IE選送中斷控制字和給中斷優先級寄存器IP選送中斷優先級字,以開放相應中斷和設定中斷優先級(若采用中斷方式)。
- 給定時器控制寄存器TCON送命令字,以啟動或禁止定時器/計數器的運行。
二、計數器初值的計算
-
定時器/計數器可用軟件隨時隨地啟動和關閉,啟動時它就自動加1計數,一直計到滿,即全為1;若不停止,計數值從全1變為全0,同時將計數溢出,置標志位為1並向CPU發出定時器溢出中斷申請。
-
對於各種不同的工作模式,最大的定時時間和計數數值不同。
-
在使用中就會出現兩個問題:
(1)要如何產生比定時器最長的定時時間還要短的時間、比計數器最多的計數次數還要少的計數次數;
(2)要如何產生比定時器最長的定時時間還要長的時間、比計數器最多的計數次數還要多的計數次數。 -
如果計數初值設定為C,則計數器從初值C開始作加1計數到計滿為全1所需要的計數值設定為D,由此便可得到如下的計算通式:
C = M -D式中,M為計數器量程,該值和計數器工作模式有關。
-
模式0時,M為$2^{13}$;
-
模式1時,M為$2^{16}$;
-
模式2和模式3時,M為$2^{8}$。
三、定時器定時方式的初值計算
-
在定時方式下,計數脈沖由單片機主脈沖經12分頻后得到,因此定時器定時時間為:
例題:
7.4 定時器/計數器T1、T0的編程和應用
- 4種工作方式中,方式0與方式1基本相同,只是計數位數不同。方式0為13位,方式1為16位。
- 由於方式0是為兼容MCS-48而設,計數初值計算復雜,所以在實際應用中,一般不用方式0,常采用方式1。
如果定時時間大於最大的可以定時時間,就利用多次的中斷
【例7-3】假設系統時鍾為12MHz,設計電路並編寫程序實現從P1.0引腳上輸出一個周期為2ms的方波,見圖7-15
基本步驟:
(1)計算T0初值:
設T0的初值為X,有
(216 −X )1 10−6=110−3
即 65536−X=1000
得X=64536,化為16進制數就是0xfc18。將高8位0xfc裝入TH0,低8位數0x18裝入TL0。
(2)采用查詢方式參考程序:
#include <reg51.h> //頭文件reg51.h
sbit P1_0=P1^0; //定義特殊功能寄存器P1的位變量P1_0
void main(void) //主程序
{ TMOD=0x01; //設置T0為方式1
TR0=1; //接通啟動T0
while(1) //無限循環
{
TH0=0xfc; //置T0高8位初值
TL0=0x18; //置T0低8位初值
do { }while(!TF0); //查詢判斷TF0是否為1,為1則T0溢出,往下 //執行,否則原地循環等待
P1_0=!P1_0; // P1.0狀態求反
TF0=0; //TF0標志清零
}
}
#include<reg51.h> / /采用中斷方式
sbit P1_0=P1^0;
void main(void)
{ TMOD=0x01; /*設置定時器T0為方式1計數*/
P1_0=0;
TH0=0xfc; /*給T0裝入初值*/
TL0=0x18; /*給T0裝入初值*/
ET0=1; /* 允許T0中斷 */
EA=1; /* 總中斷開 */
TR0=1 /* 接通T0 計數 * /
do { }while (1); /* 無限循環等待 * /
}
void T0_int(void) interrupt 1 using 1
{ P1_0=! P1_0;
TH0=0xfc;
TL0=0x18;
}
【例4】假設系統時鍾為12MHz,編程實現從P1.1引腳上輸出一個周期為1s的方波。
基本思想:
- 要在P1.1上產生周期為1s的方波,定時器應產生500ms的周期性定時,定時到則對P1.1求反。
- 由於定時時間較長,用定時器不能直接實現,直接定時時間最長的就是方式1,僅為65ms(系統時鍾12MHz)多一點。
- 可以借助P1.0輸出計數脈沖,作為計數器(如T1)的輸入信號而實現脈沖計數。
實現:
- T0定為10ms定時,每10ms對P1.0求反一次,P1.0輸出的脈沖加到定時器T1的計數輸入腳P3.5(T1腳),作為計數輸入,定時500ms需計數50次。
- T1設為方式2計數,初值X為:$2^{8}$−X=50,則X=206,所以TH1=TL1=206。
- T0設為方式1定時,則方式控制字為0x61。
#include<reg51.h>
sbit P1_0=P1^0;
sbit P1_1=P1^1;
void main(void)
{TMOD=0x61; /*設置定時器T0為方式1定時,T1為方式2計數*/
//0110 0001b
P1_0=0;
TH0=(65536 −10000) /256; /*給T0裝初值,方式1 */
TL0=(65536 −10000) %256;
TH1=206; /*給T1裝初值*/
TL1=206;
EA=1; /* 總中斷開 */
ET0=1; /* 允許T0中斷 */
ET1=1; /* 允許T1中斷 */
TR0=1;
TR1=1;
while (1);
}
void T0_int(void) interrupt 1
{
TH0=(65536 −10000) /256; /*給T0裝初值*/
TL0=(65536 −10000) %256;
P1_0=! P1_0;
}
void T1_int(void) interrupt 3
{P1_1=! P1_1; }; /* P1.1腳產生1s的方波*/ 。
【例5】擴展一個外部中斷源
- 方式2可自動重新裝載初值。此方式可省去用戶程序中重新裝初值的指令。
- 當某個定時器/計數器不使用時,可為AT89S51擴展一個負跳沿觸發的外部中斷源。
- 基本思想:把定時器溢出中斷做成外部中斷,然后把計數輸入信號接到定時器的相應引腳上T0腳(或T1腳),並把定時器被設置為方式2(自動裝入常數方式)計數工作模式,計數器TH0、TL0初值均為0FFH,並允許T0中斷,總中斷開放。
- 當檢測到T0腳(或T1腳)引腳電平發生負跳變時,計數器TF0(或TF1)溢出, TF0置“1”,單片機發出中斷請求。
擴展一個負跳沿觸發的外部中斷源,把定時器T0計數輸入引腳作為外部中斷請求信號的輸入端。
#include<reg51.h>
void main( )
{ ………
TMOD=0x06; /*設置定時器T0為方式2計數*/
TH0=0xff; /*給T0裝入初值*/
TL0=0xff; /*給T0裝入初值*/
ET0=1; /*允許T0中斷*/
EA=1; /*總中斷開*/
TF0=0; /*T0中斷溢出標志位清0*/
TR0=1 /*接通T0 計數* /
while (1) ; /*無限循環等待* /
}
/*以下為定時器T0的中斷服務程序*/
void T0_int(void) interrupt 1 using 0
{ 。。。。 } /*外中斷處理部分*/
- 本例所述的使用定時器擴展的外中斷源只能是負跳沿觸發。
- 此外,只有當定時器T0(或T1)不再使用時,才可使用本方法來擴充外部中斷源,此時定時器T0本身的功能將不能再使用,除非使用軟件來對它進行復用控制。
- 此時,P3.4腳(T0)相當於一個負跳沿觸發的外中斷請求源輸入;對P3.5也可做類似的處理。
測量脈沖寬度——利用GATE門控制
秒表
7.5 定時器/計數器T2的結構與工作方式
- AT89S52與AT89S51單片機相比,新增加了一個16位定時器/計數器T2。
- 與T2相關的特殊功能寄存器共有2個:T2CON和T2MOD。
一、T2的特殊功能寄存器T2CON和T2MOD
- 特殊功能寄存器T2CON
-
TF2:T2計數溢出中斷請求標志位。
=1:
=0:
-
EXF2:T2外部中斷請求標志位。
當由引腳T2EX(P1.1)上的負跳變引起“捕捉”或“自動重裝載”且EXEN2位為1,則置位EXF2標志位,並向CPU發出中斷請求。該標志位必須由軟件清0。
-
RCLK:串行口接收時鍾標志位。
=1:串行通信端使用T2的溢出信號作為串行通信方式1和方式3的接收時鍾;
=0:使用T1的溢出信號作為串行通信方式1和方式3的接收時鍾。
-
TCLK:串行發送時鍾標志位。
=1:串行通信端使用T2的溢出信號作為串行通信方式1和方式3的發送時鍾;
=0:串行通信端使用T1的溢出信號作為串行通信方式1和方式3的發送時鍾。
-
EXEN2:T2外部采樣允許標志位。
=1:如果T2不是正工作在串行口的時鍾,則在T2EX引腳(P1.1)上的負跳變將觸發“捕捉”或“自動重裝載”操作;
=0:在T2EX引腳(P1.1)上的負跳變對T2不起作用。
-
TR2:T2啟動/停止控制位。
- 當軟件置位TR2時,即TR2=1,則啟動T2開始計數,當軟件清TR2位時,即TR2=0,則T2停止計數。
-
C/T2* :T2的計數或定時方式選擇位.
當設置C/=1時,為對外部事件計數方式;
C/=0時,為定時方式。
-
CP/RL2*:T2捕捉/自動重裝載選擇位。
- 當設置CP/RL2=1時,如果EXEN2為1,則在T2EX引腳(P1.1)上的負跳變將觸發“捕捉”操作;
- 當設置CP/RL2=0時,如果EXEN2為1,則T2計數溢出或T2EX引腳上的負跳變都將引起自動重裝載操作;
- 當RCLK位為1或TCLK位為1,CP/RL2標志位不起作用。
- T2計數溢出時,將迫使T2進行自動重裝載操作。
-
可以通過軟件編程對T2CON 中的相關位進行設置來選擇T2 的3種工作方式。
-
T2 的3種工作方式:16位自動重裝載(遞增或遞減計數)、捕捉和波特率發生器,如表7-2所示。
下圖很重要:
- T2MOD
-
T2OE:T2輸出的啟動位。
-
DCEN:置位為1時允許T2增1/減1計數,並由T2EX引腳(P1.1)上的邏輯電平決定是增1還是減1計數。
-
— :保留位。
當單片機復位時,DCEN為0,默認T2為增1計數方式;
當把DCEN置1時,將由T2EX引腳(P1.1)上的邏輯電平決定T2是增1還是減1計數。
#define f1(a) (65536-a)/256
#define f2(a) (65536-a)%256
//a 為初值