1、相關知識
振蕩周期=1/12us;? ? ?//振蕩周期又稱 S周期或時鐘周期(晶振周期或外加振蕩周期)。
狀態周期=1/6us;
機器周期=1us;
指令周期=1~4us;
①51單片機有兩組定時器/計數器,因為既可以定時,又可以計數,故稱之為定時器/計數器。
②定時器/計數器和單片機的CPU 是相互獨立的。定時器/計數器工作的過程是自動完成的,不需要CPU 的參與。
③單片機中的定時器/計數器是根據機器內部的時鐘或者是外部的脈沖信號對寄存器中的數據加 1
2、單片機定時/計數器結構? ? T0—P3.4? ? T1—P3.5
定時/計數器的實質是加 1 計數器(16 位),由高 8 位和低 8 位兩個寄存器 THx 和TLx組成。它隨著計數器的輸入脈沖進行自加 1,也就是每來一 個脈沖,計數器就自動加 1,當加到計數器為全 1 時,再輸入一個脈沖就使計數器回零,且計數器的溢出使相應的中斷標志位置 1,向 CPU 發出中斷請求(定時 /計數器中斷允許時)。如果定時/計數器工作于定時模式,則表示定時時間已到; 如果工作于計數模式,則表示計數值已滿。可見,由溢出時計數器的值減去計數初值才是加 1 計數器的計數值。
51 單片機定時器/計數器內部結構如下所示?
2.1、工作方式寄存器 TMOD
工作方式寄存器 TMOD 用于設置定時/計數器的工作方式,低四位用于 T0,高四位用于 T1。其格式如下:
GATE = 0 時:只需要用軟件使 TCON 中的 TR0 或 TR1 為 1,就可以啟動定時/計數器工作;
GATE=1 時,要用軟件使 TR0 或 TR1 為 1,同時外部中斷引腳 INT0/1 也為高電平 時,才能啟動定時/計數器工作。
C/T =0 為定時模式;? ? ?C/T =1 為計數模式
定時器——方式1? ? ? ?串口通信——方式2
2.2、控制寄存器 TCON
TCON 的低 4 位用于控制外部中斷。TCON 的高 4 位用于控制定 時/計數器的啟動和中斷申請。
TF0,TF1:定時/計數器中斷請求控制位,當計數溢出時設為1,響應中斷后設為0
TR0,TR1:定時/計數器中斷允許標志位
3、單片機定時/計數器的工作方式
3.1 方式0? ? ? ??計數初值與計數個數的關系為:X=2 (13次方)-N
方式 0 為 13 位計數,由 TL0 的低 5 位(高 3 位未用)和 TH0 的 8 位組成。 TL0 的低 5 位溢出時向 TH0 進位,TH0 溢出時,置位 TCON 中的 TF0 標志,向 CPU 發出中斷請求。
?GATE=0 時,僅由TR0 控制與門的開啟;GATE=1時,由外中斷引腳信號INT0 和 TR0 共同控制與門的開啟
3.2 方式1(定時器使用)? ? ? ?計數初值與計數個數的關系為:X=2 (16次方)-N。
方式 1 的計數位數是 16 位,由 TL0 作為低 8 位,TH0 作為高 8 位
3.3 方式2?(串口通信使用)? ? ?計數初值與計數個數的關系為:X=2 (8次方)-N。
方式 2 為自動重裝初值的 8 位計數方式。工作方式 2 特別適合于用作較精確的脈沖信號發生器。
3.4 方式3
方式 3 只適用于定時/計數器 T0,定時器 T1 處于方式 3 時相當于 TR1=0, 停止計數。工作方式 3 將 T0 分成為兩個獨立的 8 位計數器 TL0 和 TH0。
4、定時器配置
①對 TMOD 賦值,以確定 T0 和 T1 的工作方式,如果使用定時器 0 即對 T0 配 置,如果使用定時器 1 即對 T1 配置。
②根據所要定時的時間計算初值,并將其寫入 TH0、TL0 或 TH1、TL1。
③如果使用中斷,則對 EA 賦值,打開總定時器中斷。
④使 TR0 或 TR1 置位,啟動定時/計數器定時或計數
如果我們想定時 1ms 的初值是多少呢?1ms/1us=1000。也就是要計數 1000 個,初值=65535-1000+1 (因為實際上計數器計數到 65536(2 的 16 次方)才溢出,所以后面要加 1) =64536=FC18H,所以初值即為 THx=0XFC,TLx=0X18
以定時器 0 為例介紹配置定時器工作方式 1、設定 1ms 初值,開啟定時器計數功能以及總中斷,
void time0_init(void)
{
????????TMOD|=0X01;//選擇為定時器 0 模式,工作方式 1? ? ?0X01方式1? ? 0X10——方式2
????????TH0=0XFC; //給定時器賦初值,定時 1ms
????????TL0=0X18;
????????ET0=1;//選擇使用定時器 0 中斷允許
????????EA=1;//打開總中斷
????????TR0=1;//打開定時器
}
定時器中斷實驗:通過定時器 0 中斷控制 D1 指示燈間隔 1 秒閃爍
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 ten_us){
?? ?while(ten_us--);
}sbit LED1=P2^0;
//初始化定時器0中斷的函數
void time0_init(){
?? ?TMOD|=0X01;//選擇定時器 0 模式,工作方式 1 ?為了不干擾定時器1
?? ?TH0=0XFC;//低8位 ?給定時器賦初值,定時1ms,相當于1000次脈沖
?? ?TL0=0X18;//高8位
?? ?ET0=1;//打開定時器 0 中斷允許
?? ?EA=1;//打開總開關
?? ?TR0=1;//打開定時器? ?
}/*
//初始化定時器1中斷的函數
void time1_init(){
TMOD|=0X10;//選擇為定時器 0 模式,工作方式 2
TH0=0XFC; //給定時器賦初值,定時 1ms
TL0=0X18;
ET0=1;//打開定時器 0 中斷允許
EA=1;//打開總中斷
TR0=1;//打開定時器,手動設置
}*/
void main(){
?? ?time0_init();
?? ?while(1){??
?? ?}
}//定義定時器中斷服務函數
void time0() interrupt 1{
?? ?static u16 i=0;//靜態變量,只初始化1次
?? ?TH0=0XFC;
?? ?TL0=0X18;
?? ?i++;
?? ?if(i==1000){?? ??? ?//計時1s
?? ??? ?i=0;
?? ??? ?LED1=!LED1;? ? ? ??
?? ?}?
}