定時器/計數器
應用場合:定時或延時控制、對外部事件的檢測、計數等。
計數器 就是對外部輸入脈沖的計數;
定時器 也是對脈沖進行計數完成的,計數的是MCS-51內部產生的標准脈沖,通過計數脈沖個數實現定時。
T0 P3.4
T1 P3.5
T2 P1.0
每個定時器內部結構實際上就是一個可編程的加法器,由編程來設置它工作在定時狀態還是計數狀態。
單片機復位,定時器數據清零。
定時器/計數器組成: 兩個16位的定時器T0和T1,以及他們的工作方式寄存器TMOD和控制寄存器TCON等組成。
定時器T0和T1各由兩個8位特殊功能寄存器TH0、TL0、TH1、TH1構成。
TH0(8位)、TL0(8位) =》16位的定時計數器 T0
TH1(8位)、TL1 (8位)=》16位的定時計數器 T1
TH0和TL0:存放定時器T0的初值或計數結果;TH0存放高8位,TL0存放低8位
TH1和TL1:存放定時器T1的初值或計數結果;TH·存放高8位,TL·存放低8位
TMOD:用於設置定時器的工作模式和工作方式;工作方式4種(0、1、2、3)
TCON:用於啟動和停止定時器的計數,並控制定時器的狀態。
TMOD
M1 M0——工作方式選擇位
M1 M0 0 0 方式0,13位定時器/計數器(TH0用低5位,TL0用8位) 0 1 方式1,16定時器/計數器 (TH0用8位,TL0用8位;每次溢出TH0,TL0都會置零) 1 0 方式2,8位常數自動重新裝載 1 1 方式3,僅適用於T0,T0分為兩個8位;T1停止計數
TCON
特殊功能寄存器TCON的高4位為定時器的運行控制位和溢出標志位,低4位為外部中斷的觸發方式控制位和鎖存外部中斷請求源。
TCON格式如下:
D7 D6 D5 D4 D3 D2 D1 D0
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
高四位功能:
(1)TF1、TF0 計數溢出標志位
(2)TR1、TR0 計數支行控制位
TRX=1: 啟動定時器/計數器工作
TRX=0: 停止定時器/計數器工作
低四位功能:(外部中斷)
IE1:外部中斷1請求標志位,當外部中斷1被觸發時置1。
IT1:外部中斷1觸發方式選擇位。當IT1=0,為低電平觸發方式;當IT1=1,為下降沿觸發方式。
IE0:外部中斷0請求標志位,當外部中斷0被觸發時置1。
IT0:外部中斷0觸發方式選擇位。 當IT0=0,為低電平觸發方式;當IT0=1,為下降沿觸發方式。
工作原理:
1、通過設置TMOD、TCON 設置定時計數器的工作方式以及工作模式
2、設置定時計數器T0和T1這兩個定時計數器寄存器的一個初值
每個機器周期到來時:T0++;當TL0=0xff,TH0++
當TH0=0xff,並且TL0=0xff,稱作溢出中斷(255*255=65535)
初值=T0溢出值-計數次數
指令周期=機器周期X2
TH0=(定時計數器的初值)/256;
TL0=(定時計數器的初值)%256;
定時器設置
(1) 設置TMOD TMOD=0X01;
(2) 計算出初值
(3) 開放總中斷 EA=1;
(4) 啟動定時計數器 TR0(1)=1;
(5) 設置中斷程序
void fun(void) interrupt 1 —— 定時計數器0溢出中斷服務程序
void timer0(void) interrupt 1 using 1 { …………… }

#include <STC89C51RC.H> typedef unsigned char u8; typedef unsigned int u16; u16 timer; sbit led=P1^0; void Init_timer0(void) { TMOD = 0x01; //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響 TH0=(65535-50000)/256; //給定初值,這里使用定時器最大值從0開始計數一直到65535溢出 TL0=(65535-50000)%256; EA=1; //總中斷打開 ET0=1; //定時器中斷打開 TR0=1; //定時器開關打開 } void main (void) { Init_timer0(); while (1) //主循環 { //主循環中添加其他需要一直工作的程序 // delay(100);//執行100次 } } void timer0_Service(void) interrupt 1 { TH0=(65535-50000)/256; //重新設置初值 TL0=(65535-50000)%256; timer++; if(timer==20) { timer=0; led=~led; } }
定時器1

/*----------------------------------------------- 名稱:定時器1 論壇:www.doflye.net 編寫:shifang 日期:2009.5 修改:無 內容:通過定時讓LED燈閃爍 ------------------------------------------------*/ #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 sbit LED=P1^0; //定義LED端口 /*------------------------------------------------ 定時器初始化子程序 ------------------------------------------------*/ void Init_Timer1(void) { TMOD |= 0x10; //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響 TH1=0x00; //給定初值,這里使用定時器最大值從0開始計數一直到65535溢出 TL1=0x00; EA=1; //總中斷打開 ET1=1; //定時器中斷打開 TR1=1; //定時器開關打開 } /*------------------------------------------------ 主程序 ------------------------------------------------*/ main() { Init_Timer1(); while(1); } /*------------------------------------------------ 定時器中斷子程序 ------------------------------------------------*/ void Timer1_isr(void) interrupt 3 using 1 { TH1=0x00; //重新賦值 TL1=0x00; LED=~LED; //LED閃爍 }
定時器2

/*----------------------------------------------- 名稱:定時器2 論壇:www.doflye.net 編寫:shifang 日期:2009.5 修改:無 內容:通過定時讓LED燈閃爍 ------------------------------------------------*/ #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 sbit LED=P1^0; //定義LED端口 /*------------------------------------------------ 定時器初始化子程序 ------------------------------------------------*/ void TIM2Inital(void) { RCAP2H = (65536-60000)/256;//晶振12M 60ms 16bit 自動重載 RCAP2L = (65536-60000)%256; ET2=1; //打開定時器中斷 EA=1; //打開總中斷 TR2=1; //打開定時器開關 } /*------------------------------------------------ 主程序 ------------------------------------------------*/ main() { TIM2Inital(); while(1); } /*------------------------------------------------ 定時器中斷子程序 ------------------------------------------------*/ void TIM2(void) interrupt 5 using 1//定時器2中斷 { TF2=0; LED=~LED; //指示燈反相 }

#include "reg52.h" //此文件中定義了單片機的一些特殊功能寄存器 #include <absacc.h> //包含絕對地址訪問庫函數 #define SEG1 XBYTE[0xffec] #define SEG2 XBYTE[0xffed] #define SEG3 XBYTE[0xffee] #define SEG4 XBYTE[0xffef] typedef unsigned int u16; //對數據類型進行聲明定義 typedef unsigned char u8; sbit led=P1^0; //定義P10口是led //共陽 u8 code smg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 //0-9 }; /******************************************************************************* * 函 數 名 : Timer0Init * 函數功能 : 定時器0初始化 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void Timer0Init() { TMOD|=0X01;//選擇為定時器0模式,工作方式1,僅用TR0打開啟動。 TH0=0XFC; //給定時器賦初值,定時1ms TL0=0X18; ET0=1;//打開定時器0中斷允許 EA=1;//打開總中斷 TR0=1;//打開定時器 } int count; /******************************************************************************* * 函 數 名 : main * 函數功能 : 主函數 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void main() { SEG1=SEG2=SEG3=SEG4=0xff;//全滅 Timer0Init(); //定時器0初始化 while(1) { SEG4 = smg[count%10]; SEG3 = smg[count/10%10]; SEG2 = smg[count/100%10]; SEG1 = smg[count/1000%10]; } } /******************************************************************************* * 函 數 名 : void Timer0() interrupt 1 * 函數功能 : 定時器0中斷函數 * 輸 入 : 無 * 輸 出 : 無 *******************************************************************************/ void Timer0() interrupt 1 { static u16 i; TH0=0XFC; //給定時器賦初值,定時1ms TL0=0X18; i++; if(i==2000) { i=0; led=~led; count++; } }
定時加數碼管9999計數

#include<reg52.h>//包含訪問sfr庫函數 #include<intrins.h>//包含訪問內聯庫函數 #include <absacc.h> typedef unsigned int uint; //對數據類型進行聲明定義 typedef unsigned char uchar; sbit P10=P1^0; sbit k1=P3^2; //包含絕對地址訪問庫函數 #define SEG1 XBYTE[0xffec] #define SEG2 XBYTE[0xffed] #define SEG3 XBYTE[0xffee] #define SEG4 XBYTE[0xffef] //共陽 uchar code smg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 };//0-9 /* 精確定時1秒閃爍LED */ uint count; main() { RCAP2H=0X10; //賦值52 0X1000,溢出30次等於1秒 RCAP2L=0X00; TR2=1; //啟動定時器 ET2=1; //打開定時器0中斷 EA=1; //打開總中斷 SEG1=SEG2=SEG3=SEG4=0xff;//全滅 while(1) { SEG4 = smg[count%10]; SEG3 = smg[count/10%10]; SEG2 = smg[count/100%10]; SEG1 = smg[count/1000%10]; } } //定時器2中斷 timer2() interrupt 5 //定時器2中斷是5號 { static uchar t; TF2=0; t++; if(t==30) { t=0; count++; P10=~P10; } }
定時器0
#include<reg52.h>//包含訪問sfr庫函數 sbit P10=P1^0; sbit k1=P3^2; u16 i; main() { TMOD=0X01;//定時器0,16位工作方式 TR0=1; //啟動定時器 ET0=1; //打開定時器0中斷 EA=1; //打開總中斷 while(1) { } } //定時器0中斷 timer0() interrupt 1 //定時器0中斷是1號 { TH0=0X00; //寫入定時器0初始值0X0005 TL0=0X06; while(k1); P10=~P10;//反轉LED燈的狀態 }
精確定時1秒

#include<reg52.h>//包含訪問sfr庫函數 #include<intrins.h>//包含訪問內聯庫函數 typedef unsigned int u16; //對數據類型進行聲明定義 typedef unsigned char uchar; sbit P10=P1^0; sbit k1=P3^2; /* 精確定時1秒閃爍LED */ main() { RCAP2H=0X10; //賦值52 0X1000,溢出30次等於1秒 RCAP2L=0X00; TR2=1; //啟動定時器 ET2=1; //打開定時器0中斷 EA=1; //打開總中斷 while(1) { } } //定時器2中斷 timer2() interrupt 5 //定時器2中斷是5號 { static uchar t; TF2=0; t++; if(t==30) { t=0; P10=~P10; } }
外中斷

#include<reg52.h>//包含訪問sfr庫函數 sbit P10=P1^0; sbit K1=P3^2; /* 外中斷的用法。也就是外部 IO 的中斷 INT0,和 INT1。 對應的引腳是 P32 和 P33。 在我們的電路圖中,P32 也就是接在 K1 的引腳。 所以當我們按下 P32 接到地的時候,可以觸發一個 INT0 中斷. 當然,必須預先初始化才會啟動。 */ main() { IT0=1;//外中斷跳變產生中斷 EX0=1; EA=1; //打開總中斷 while(1); } int0() interrupt 0 { P10=~P10; }