基于单片机定时器/计数器的时钟设计及计数设计
基于單片機定時器/計數器的時鐘設計以及計數設計
- 第一部分 前言
- 第二部分 定時器/計數器的原理
- 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模式
| 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模式
| 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類似。
??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不能位尋址)
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++); }??以上就是本次定時器/計數器的全部內容,希望通過本次的講解能夠加深大家對于定時器/計數器以及中斷的理解。文章的內容可能存在部分不足之處,如有錯誤,請在評論區指出,謝謝。如果大家覺得文章有用,麻煩點贊關注,感謝支持,后續將會推出單片機的進階設計文章。
總結
以上是生活随笔為你收集整理的基于单片机定时器/计数器的时钟设计及计数设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每个开发人员现在应该下载的十种必备工具!
- 下一篇: DBCP连接池配置优化分析