基于單片機定時器/計數器的時鐘設計以及計數設計
- 第一部分 前言
- 第二部分 定時器/計數器的原理
- MCS-51定時器/計數器的結構
- 定時器/計數器相關特殊功能暫存器
- 定時器/計數器作業方式
- 第三部分 定時器/計數器編程方法
- 第四部分 定時器/計數器仿真設計
- 設計案例一
- 原理圖
- 動態仿真結果
- 代碼
- 設計案例二
- 原理圖
- 動態仿真結果
- 代碼
第一部分 前言
??本次單片機基礎實驗將會通過在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單片機為例講解定時器/計數器的基本結構,

??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類似,
- IE1—外部中斷請求1的中斷請求標志位,意義與IE0類似,
- 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,其二進制編碼如下
??再將16位的二進制編碼去除最高的3位,保留后面13位,并取低5位寫入到TL0(TL1),高8位寫入到TH0(TH1),具體操作如下
??其中,11000B是TL0(TL1)對應的低5位,其16進制編碼為18H,而1110 0000這8位為TH0(TH1)的內容,其16進制編碼為0E0H,
??當定時器/計數器作業于方式0且確定了定時時間T1后,其計數初值N的計算公式為
??式中,fosc為系統時鐘振蕩頻率,
??假設單片機的晶振選為12MHz,需要用T0進行2ms定時控制,則T0的初值N計算為
??則對應的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的計算公式為:
??則寫入到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可以構成兩個定時器或者一個定時器和一個計數器,
第三部分 定時器/計數器編程方法
定時器的初始化編程包括:
- 設定定時器作業模式(設定TMOD);
- 設定定時器計數初值(設定THx/TLx);
- 允許定時器中斷(IE);
- 啟動定時器(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++);
}
??以上就是本次定時器/計數器的全部內容,希望通過本次的講解能夠加深大家對于定時器/計數器以及中斷的理解,文章的內容可能存在部分不足之處,如有錯誤,請在評論區指出,謝謝,如果大家覺得文章有用,麻煩點贊關注,感謝支持,后續將會推出單片機的進階設計文章,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/248091.html
標籤:其他
上一篇:陳玉龍:永懷少年心 不改凌云志
下一篇:資料結構---二叉樹
