Keil C51學習 5 定時器/計數器


 

  

 

定時器/計數器

應用場合:定時或延時控制、對外部事件的檢測、計數等。

計數器 就是對外部輸入脈沖的計數;

定時器 也是對脈沖進行計數完成的,計數的是MCS-51內部產生的標准脈沖,通過計數脈沖個數實現定時。

T0  P3.4

T1  P3.5

T2  P1.0

 

每個定時器內部結構實際上就是一個可編程的加法器,由編程來設置它工作在定時狀態還是計數狀態。

 

單片機復位,定時器數據清零。

定時器/計數器組成: 兩個16位定時器T0T1,以及他們的工作方式寄存器TMOD控制寄存器TCON等組成。

定時器T0T1各由兩個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 
{ 
…………… 
}
timer0 是函數名,可以任意取,但是不要和關鍵字重復。
interrupt 1 是非常重要的,interrupt 是關鍵字,表示中斷,1 表示 1 號中斷即定時器 0 中斷。
 
中斷號 0~4,分別表示外部中斷 0→定時器 0→外部中斷 1→定時器 1→串口中斷。
 
using 1 表示使用第 1 組寄存器,51 單片機中一共有 4 組寄存器,每組寄存器是 R0~R7。
 
 使用模式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

/*-----------------------------------------------
  名稱:定時器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閃爍

}
定時器1

 定時器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;               //指示燈反相
   
}
定時器2

 

   中斷加數碼管9999計數
#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計數器

定時加數碼管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;
    }
}
數碼管9999計數

 

 

定時器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;
    }
}
定時1秒閃爍

 外中斷

#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;
}
外中斷

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM