基於單片機定時器/計數器的時鐘設計及計數設計

第一部分 前言

  本次單片機基礎實驗將會通過在Proteus軟件中畫原理圖,然後Keil軟件下編寫源程序並編譯形成可執行文件.hex,下載源程序,進行Protues和Keil的聯合仿真運行,最終對單片機仿真有初步的認識。 通過本篇文章定時器/計數器T0、T1的工作方式選擇和編程方法。學習Proteus瞭解定時器/計數器中斷服務程序的設計方法

以下是本篇文章正文內容,所設計的案例可供參考


第二部分 定時器/計數器的原理

MCS-51定時器/計數器的結構

  MCS-51單片機根據不同型號,其片內定時器/計數器數目不同。8051單片機有兩個16位定時器/計數器寄存器:Timer0(T0定時器)與Timer1(T1定時器1)。8052除這兩個定時器/計數器外還增加了1個Timer2(T2定時器),而這3個都可設置爲定時器或事件計數器。當其作爲“定時器”功能時,它是對標準時鍾計數,每個時鐘週期寄存器自動增1。由於MCS-51單片機的一個機器週期由12個振盪器週期組成,計數速率是振盪器頻率的1/12。作爲“計數器”功能,寄存器在響應相應的外部輸入引腳T0、T1或T2(在8052中)由1至0的轉變而增1。不論是“定時器”還是外部事件“計數器”,其工作原理是一樣的,即定時器/計數器電路中的內部計數器從某一預定值(此值是可編程的)開始計數,當累計到最大值時產生溢出,並同時會建立一個相應的溢出標誌(即中斷標誌位)。除了“定時器”或“計數器”選擇外,定時器0與定時器1有4種工作方式需要選擇。在8052單片機中的定時器T2有3種操作方式:“捕獲”、“自動重裝入”與“波特率生成器”。下面主要以AT89C51單片機爲例講解定時器/計數器的基本結構。
在這裏插入圖片描述

圖1 單片機的定時器/計數器結構框圖

  AT89C51單片機片內定時器/計數器的結構如圖1所示。定時器內部實質上是16位加法計數器,其控制電路受軟件控制。當用作定時器時,對機器週期計數,每過一個機器週期,計數器加1。由於每個機器週期包含12個振盪信號週期,所以加1計數器的計數頻率爲振盪器信號頻率的1/12。當用作計數器功能時,加1計數器的計數脈衝取自外部輸入端T0(P3.4)和T1(P3.5),只要這些引腳上有從“1”到“0”的負跳變,計數器就加1。CPU在每個機器週期的S5P2時刻對外部輸入狀態進行採樣,計數器加1的執行是在檢測到跳變後的下一個機器週期的S3P1時刻。由於需要兩個機器週期來識別一個從“1”到“0”的負跳變,所以最大計數頻率爲振盪信號頻率的1/24。而外部時鐘脈衝持續爲0和爲1的時間不能少於一個機器週期。
  兩個可編程的16位定時器 /計數器T0 和 T1
  - T0 = TH0(高8位) + TL0(低8位)
  - T1 = TH1(高8位) + TL1(低8位)


定時器/計數器相關特殊功能寄存器

  • TMOD:控制定時器/計數器的工作方式
  • TCON:控制定時器/計數器的運行
  • IE、IP:定時器/計數器的中斷控制

1. TMOD
  TMOD用來選擇定時器/計數器的工作模式和工作方式,它的字節地址是89H,但該寄存器不能進行位尋址。在這裏插入圖片描述

  • GATE=0,運行控制位 TR0/TR1(=1) 控制 T0/T1 啓動;
  • GATE=1,INT0/1 (=1) 及運行控制位TR0/TR1(=1)控制T0/T1啓動,可用於外部脈衝寬度測量
  • C/T=0,用作定時器(定時功能通過計數實現,計數脈衝來自內部系統時鐘輸入,一個機器週期產生一個計數脈衝);
  • C/T=1,用作計數器(對外部脈衝計數,外部輸入脈衝發送負跳
    變時加1)

T0模式

M1 M0 功能
0 0 13 位定時器/ 計數器,TL1 低5 位 + TH1全8 位,最大值爲8192
0 1 16 位定時器/ 計數器,TL1、TH1 全用,最大值65.536ms;
1 0 8 位自動重裝載定時器,當溢出時將TH1 存放的值自動重裝入TL1,最大值爲256;
1 1 定時器/ 計數器1 此時無效(停止計數)

T1模式

M1 M0 功能
0 0 13 位定時器/ 計數器,TL1 低5 位 + TH1全8 位,最大值爲8192
0 1 16 位定時器/ 計數器,TL1、TH1 全用,最大值65.536ms;
1 0 8 位自動重裝載定時器,當溢出時將TH1 存放的值自動重裝入TL1,最大值爲256;
1 1 定時器0 爲雙8 位定時器/ 計數器,TL0 作爲一個8 位定時器/ 計數器,通過標準定時器0 的控制位控制,TH0 僅作爲一個8 位定時器,由定時器1 的控制位控制。

2.TCON
  TCON寄存器的字節地址爲88H,可進行位尋址。高4位分別爲定時器/計數器的啓動控制和溢出中斷標誌,低4位與外部中斷控制有關,
在這裏插入圖片描述
各標誌位的功能:


1. IT0—選擇外部中斷請求0爲跳沿觸發方式還是電平觸發方式:
IT0=0,爲電平觸發方式。
IT0=1,爲跳沿觸發方式。
  可由軟件置“1”或清“0”。
2. IE0—外部中斷請求0的中斷請求標誌位。
IE0=0,無中斷請求。
IE0=1,外部中斷0有中斷請求。
當CPU響應該中斷,轉向中斷服務程序時,由硬件清“0”IE0
**3. IT1—外部中斷請求1爲跳沿觸發方式還是電平觸發方式,意義與IT0類似。







  1. IE1—外部中斷請求1的中斷請求標誌位,意義與IE0類似。
  2. TF0 —T0溢出中斷請求標誌位。**
      T0計數後,當最高位產生溢出時,由硬件置“1”TF0,向CPU申請中斷,CPU響應TF0中斷時,清“0”TF0,TF0也可由軟件清0。

6. TF1—T1的溢出中斷請求標誌位,功能和TF0類似。
   TR1、TR0 2個位與中斷無關,僅與定時器/計數器T1和T0有關。

3.IE
  中斷允許寄存器:CPU對中斷源的開放或屏蔽,由片內的中斷允許寄存器IE控制。字節地址爲A8H,可位尋址。格式如下:
在這裏插入圖片描述
IE中各位的功能如下:


1. EA:中斷允許總控制位
EA=0:CPU屏蔽所有的中斷請求(CPU關中斷) ;
EA=1:CPU開放所有中斷(CPU開中斷) 。
五個中斷源的中斷請求是否允許,還要由IE中對應的5箇中斷請求允許控制位的狀態來決定。


2. ES:串行口中斷允許位
ES=0:禁止串行口中斷;
ES=1:允許串行口中斷。

3. ET1:定時器/計數器T1的溢出中斷允許位
ET1=0:禁止T1溢出中斷;
ET1=1:允許T1溢出中斷。

4. EX1:外部中斷1中斷允許位
EX1=0:禁止外部中斷1中斷;
EX1=1:允許外部中斷1中斷。

5. ET0:定時器/計數器T0的溢出中斷允許位
ET0=0:禁止T0溢出中斷;
ET0=1:允許T0溢出中斷。

6. EX0:外部中斷0中斷允許位。
EX0=0:禁止外部中斷0中斷;
EX0=1:允許外部中斷0中斷。

MCS-51復位後,IE清0,所有中斷請求被禁止。若使某一箇中斷源被允許中斷,除了IE相應的位被置“1” ,還必須使EA位=1。改變IE的內容,可由位操作指令或字節操作指令來實現。




定時器/計數器工作方式

  在MCS-51系列單片機中,定時器/計數器(T0、T1)具有多種工作方式,當選擇工作方式不同,定時/計數器的使用方法差別很大。MCS-51單片機片內的定時器/計數器可以通過對特殊功能寄存器TMOD中的控制位 的設置來選擇定時器方式或計數器方式;通過對M1 M0兩位的設置來選擇定時器/計數器的四種工作方式,下面具體講解定時器/計數器的工作方式。

1. 工作方式0

  定時器/計數器0、1在工作方式0時的電路邏輯結構見圖9-2。工作方式0(M1 M0 = 0 0)是13位計數結構的工作方式,其計數器由TH的全部8位和TL的低5位構成,TL的高3位不使用。當 =0時,定時器/計數器0、1處於定時工作方式,多路開關接通振盪脈衝的12分頻輸出,13位計數器依次進行計數。當 =1時,定時器/計數器0、1處於計數工作方式,多路開關接通計數引腳(T0),外部計數脈衝由腳T0輸入。當計數脈衝發生負跳變時,計數器加1。
  當TL的低5位溢出時,都會向TH進位,而全部13位計數器溢出時,則會向計數器溢出標誌位TF0進位。同時,GATA位的狀態決定定時器運行控制取決於TR0一個條件還是TR0和/INT0引腳這兩個條件。當GATA=1時,由於GATA信號封鎖了與門,使引腳/INT0信號無效。而這時候如果TR0=1,則接通模擬開關,使計數器進行加法計數,即定時/計數器工作。而TR0=0,則斷開模擬開關,停止計數,定時器/計數器不能工作。當GATA=0時,與門的輸出端由TR0和INT0電平的狀態確定,此時如果TR0=1,INT0=1與門輸出爲1,允許定時器/計數器計數,在這種情況下,運行控制由TR0和INT0兩個條件共同控制,TR0是確定定時/計數器的運行控制位,由軟件置位或清“0”。

在這裏插入圖片描述
  在工作方式0下,計數器的計數值X範圍爲1~8192(2131)。由於MCS-51單片機的T0和T1採用加計數,因此TH0(TH1),TL0(TL1)的初值N=8192-X。如當計數值X=1000,則計數初值N=7192=1C18H,那麼TH0(TH1),TL0(TL1)的值分別爲0E0H和18H。由於TL0(TL1)爲低5爲有效,所以該計數初值N不能簡單地分成高8位和低8位賦值給TH0(TH1),TL0(TL1)。當計數初值N=7192=1C18H,其二進制編碼如下

1C18H=0001 1100 0001 1000B

  再將16位的二進制編碼去除最高的3位,保留後面13位,並取低5位寫入到TL0(TL1),高8位寫入到TH0(TH1),具體操作如下

1C18H=0001 1100 0001 1000 = 1110 0000 11000B

  其中,11000B是TL0(TL1)對應的低5位,其16進制編碼爲18H,而1110 0000這8位爲TH0(TH1)的內容,其16進制編碼爲0E0H。
  當定時器/計數器工作於方式0且確定了定時時間T1後,其計數初值N的計算公式爲


N=8192-(T1×fosc/12)

  式中,fosc爲系統時鐘振盪頻率。
  假設單片機的晶振選爲12MHz,需要用T0進行2ms定時控制,則T0的初值N計算爲

N=8192-T1×fosc/12=8192-2×10-3×12×106/12=6192=1830H=0001 1000 0011 0000B

  則對應的13位二進制編碼爲1100 0001 1 0000則TH0=0C1H,TL0=10H

2. 工作方式1

定時器/計數器0、1工作於方式1時,其電路邏輯結構如圖所示。
在這裏插入圖片描述

  工作方式1(M1 M0=0 1)是16位計數結構的工作方式。方式0和方式1的區別僅在於計數器的位數不同,方式0爲13位,而方式1則爲16位,由TH0作爲高8位,TL0爲低8位,有關控制狀態字(GATA、TF0、TR0)和方式0相同。
  在工作方式1下,計數器的計數值X範圍是:1~65536
  當定時器/計數器工作於方式1且確定了定時時間T1後,其計數初值N的計算公式爲:



N=65536-(T1×fosc/12)

  則寫入到8位寄存器TH0(TH1),TL0(TL1)值分別爲
  TH0(TH1)=N/256
  TL0(TL1)=N%256

3. 工作方式2

  當M1 M0=1 0時,定時器/計數器0、1處於工作方式2,此時其電路邏輯結構如圖9-4所示。以定時/計數器0爲例,定時/計數器1與之完全一致。
在這裏插入圖片描述

4. 工作方式3

  當M1 M0 =1 1時,定時器/計數器工作於方式3下。方式3只適用於定時器T0,若將T1置爲方式3,則它將停止計數,其效果相當於置TR1=0,即關閉定時器T1。當T0工作在方式3時,TH0和TL0被分成兩個相互獨立的8位計數器,其電路邏輯結構如圖所示。
在這裏插入圖片描述
  在工作方式3模式下,TL0既可以作爲計數器使用,也可以作爲定時器使用,定時器/計數器0的各控制位和引腳信號全歸它使用。其功能和操作與方式0或方式1完全相同。但TH0的功能受到限制,只能作爲簡單的定時器使用,而且由於定時器/計數器0的控制位已被TL0佔用,因此只能借用定時器/計數器1的控制位TR1和TF1,也就是以計數溢出去置位TF1,TR1則負責控制TH0定時器的啓動和停止。由於TL0既能作定時器也能作計數器使用,而TH0只能作定時器使用而不能作計數器使用,因此在方式3模式下,定時/計數器0可以構成兩個定時器或者一個定時器和一個計數器。

第三部分 定時器/計數器編程方法

定時器的初始化編程包括:

  1. 設置定時器工作模式(設置TMOD);
  2. 設置定時器計數初值(設置THx/TLx);
  3. 允許定時器中斷(IE);
  4. 啓動定時器(TCON)。

例如:

  • 設置定時器工作模式(TMOD不能位尋址)
    TMOD = 0x01; T0工作在模式 1下,16位定時器
  • 設置定時器計數初值
    計算初值公式 (T0定時模式2,8):
    TH0=(28- 計數值) ; \ 8192 1s, 1us=110^6 ,50000,50ms
    TL0=(28 -計數值);
    計數值=定時時間/ 機器週期; 如果時鐘頻率fosc=12MHZ,則機
    器週期=12


    時鐘週期=12*1/fosc=1us。 6mhz,
    PS:如果要求定時器按某固定時間間隔不斷觸發,需要在中斷服務程
    序中再次設置定時器計數初值(模式2除外),否則,中斷服務程序以該模
    式下的最大定時值工作。




  • 允許定時器中斷(中斷號)
    EA=1;ET0=1
  • 啓動定時器
    定時器T0:TCON=0x10 或者 TR0=1

第四部分 定時器/計數器仿真設計

設計案例一

  基於上述原理可以設計一個60s計時的秒錶,完成秒錶電路的設計與編程調試。

原理圖

在這裏插入圖片描述
  定時器T0或T1實現秒錶的計時功能,工作模式不限,計時60s後自動從0開始重新計時, INT0中斷方式實現秒錶的啓動和暫停計時; INT1中斷方式實現秒錶的計時重置。

動態仿真結果

在這裏插入圖片描述
在這裏插入圖片描述

代碼

Keil代碼如下:

#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit duan = P2^0;
sbit wei = P2^1;
sbit int0=P3^2;
sbit int1=P3^3;
uchar code LED_D[]={
   
      0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar code LED_W[]={
   
      0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uchar count=0;
uchar Time=0;

void Delay(uint x);//延遲函數
void Display2(uchar W1, Time);//顯示函數
void QP();//清屏函數
//主函數
void main()
{
   
      
   QP(); 
   TMOD=0x01;//設置定時器工作方式  
   TH0=(65536-50000)/256;//計算初值,高8位
   TL0=(65536-50000)%256;//計算初值,第8位
   ET0=1;
   EA=1;  //開總中斷 
   while(1)
    {
   
                  
       if(int0==0)
   {
   
      Delay(100);
   if(int0==0){
   
      
   TR0=!TR0;
   while(int0==0);}}
   if(int1==0){
   
      
   Delay(100);
   if(int1==0)
   {
   
      Time=0;
   }}
   Display2(6,Time);    
 }
 }
void LED_Flash() interrupt 1//中斷函數
{
   
      
   EA=0;//關總中斷
   TH0=(65536-50000)/256;//重裝初值 
   TL0=(65536-50000)%256;//重裝初值
   if(++count==20)     //開始計數
     {
   
      
	  count=0;
	 Time++;
	 if(Time==61)
	 Time=0;  
 }
    EA=1;
}
void Int0() interrupt 0
{
   
      
    if(int0==0)
   {
   
      Delay(100);
   if(int0==0)
   {
   
      
   TR0=!TR0;
   while(int0==0);
   }
   }
}
void Int1() interrupt 2//中斷函數
{
   
       EA=1;
 ET0=1;
    if(int1==0){
   
      
   Delay(10);
   if(int1==0)
   {
   
      Time=0;
   }
   }
}
void Display2(uchar W1, Time)//顯示函數
{
   
      
	 uchar shi,ge;
 	 shi = Time/10;
	 ge = Time%10;
	 P0 = LED_D[shi];
	 duan = 1;   duan = 0;
	 P0 = LED_W[W1];
	 wei = 1; 
	 wei = 0;
	 Delay(3);
	 QP(); 
	 P0 = LED_D[ge];
	 duan = 1;
	 duan = 0; 
	 P0 = LED_W[W1+1];
	 wei = 1;
	 wei = 0; 
	 Delay(3); 
	 QP(); 
} 
void QP()
{
   
      
	 P0=0x00;
	 duan = 1; duan = 0; 
	 wei = 1; wei = 0;
}
void Delay(uint x)   //延時
{
   
      
	 uchar t;
	 while(x--) for(t=0;t<110;t++);
}

設計案例二

利用T0、T1計數器功能,實現按鍵計數,計數值分別在2個4位數碼管上顯示。

原理圖

  • 利用定時器T0工作模式2,中斷方式,計數初值爲0,數碼管顯示3位數
  • T1工作模式不限,非中斷方式,計數初值爲256,數碼管顯示3位數
  • INT0中斷方式實現T0、T1計數清零
    在這裏插入圖片描述

動態仿真結果

在這裏插入圖片描述
  通過不同的按鍵來實現對應的計數功能,利用定時器的計數功能可以使得單片機得到快速響應。

代碼

#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit duan = P2^0;
sbit wei = P2^1;
uchar code LED_D[]={
   
      0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar code LED_W[]={
   
      0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uint count1,count2;   
void Delay(uint x);
void Display2(uchar W1,uint count);
void QP();
void main()
{
   
      
	   QP(); 
	   EA=1; //開總中斷
	   TMOD=0x46; //設置定時器工作方式   
	   TH0=TL0=0; //設定初值
	   TH1=1;TL1=0;
	   ET0=1;
	   EX0=1;
	   IT0=1;
	   TR0=1;
	   TR1=1;
	   while(1)
	    {
   
       
	      if(TF1==1) TF1=0;
	 count1 = TL0;
	 count2 = TH1*256+TL1;
	 Display2(1,count1);          
	 Display2(5,count2);       
 }
}
void Flash() interrupt 1
{
   
      
	   EA=0;
	   TL1=0;
	   EA=1;
}
void Clear() interrupt 0
{
   
      
   TL0=0; 
   TL1=0;
}
void Display2(uchar W1, uint count)
{
   
      
	 uchar  bai,shi,ge;
	 bai = count%1000/100;
	 shi = count%100/10;
	 ge = count%10;
	 P0 = LED_D[bai];
	 duan = 1;   duan = 0;
	 P0 = LED_W[W1];
	 wei = 1; 
	 wei = 0;
	 Delay(3);
	 QP(); 
	 P0 = LED_D[shi];
	 duan = 1;
	 duan = 0; 
	 P0 = LED_W[W1+1];
	 wei = 1;
	 wei = 0;
	 Delay(3); 
	 QP();
	 P0 = LED_D[ge];
	 duan = 1;
	 duan = 0;
	 P0 = LED_W[W1+2];
	 wei = 1;
	 wei = 0;
	 Delay(3); 
	 QP(); 
}  
void QP()
{
   
      
	 P0=0x00;
	 duan = 1; duan = 0; 
	 wei = 1; wei = 0;
}
void Delay(uint x) 
{
   
      
	 uchar t;
	 while(x--) for(t=0;t<110;t++);
}

  以上就是本次定時器/計數器的全部內容,希望通過本次的講解能夠加深大家對於定時器/計數器以及中斷的理解。文章的內容可能存在部分不足之處,如有錯誤,請在評論區指出,謝謝。如果大家覺得文章有用,麻煩點贊關注,感謝支持,後續將會推出單片機的進階設計文章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章