【藍橋杯單片機08】定時器的基本原理與應用
廣東職業技術學院 歐浩源
1、什么是定時/計數器?
在沒有鍾表的時候,定時的方式通過有一注香的時間,或者一桶水的時間。前者燒香不斷減少是減法,后者滴水不斷增加是加法。
定時/計數器,是一種能夠對內部時鍾信號或外部輸入信號進行計數,當計數值達到設定要求時,向CPU提出中斷處理請求,從而實現定時或者計數功能的外設。定時/計數器的最基本工作原理是進行計數。作為定時器時,計數信號的來源選擇周期性的內部時鍾脈沖;用作計數器時,計數信號的來源選擇非周期性的外部輸入信號。
不管是定時器還是計數器,本質上都是計數器。
定時器的工作原理與計數初值計算,可以參考以下例子:
2、51單片機的定時/計數器
51單片機有兩個定時/計數器T0和T1,為16位加法計數器,由低8位TLx和高8位THx兩個寄存器組成,最大計數值為65535個計數脈沖。
該加1計數器的計數脈沖來源有2個:
<1> 系統時鍾振盪器輸出的12分頻。
<2> T0或T1引腳輸入的外部脈沖信號。
每接收到一個計數脈沖,計數器就會加1,當計數值累計至全為1時(8位255,13位8191,16位65535),再輸入一個計數脈沖,計數器便會溢出回零,並且計數器的溢出是TCON寄存器的TF0或TF1位置1,同時向內核提出中斷請求。如果定時/計數器工作於定時模式,則表示間隔定時時間到,如果工作與計數模式,則表示計數值已滿。
假設單片機的外部晶振為12MHz,那么,經過12分頻后輸入計數器的計數脈沖為1MHz,即每個脈沖的周期為1us。因此定時器T0的16位工作模式最大的定時時間為65535us,65.5ms。如果要定時10ms的話,計數器就不能夠從0開始計數了,必須給它一個計數初值。怎么計算這個初值呢?
要定時10ms,則相當於計數10000個脈沖后計數器的值就到達65535了,那么開始計數的這個地方就是計數初值。
65535 - 10000 = 55535 = 0xd8ef
把這個計算得到的初值寫入TH0和TL0寄存器即可:
TH0 = 0xd8;或者 TH0 = (65535 - 10000) / 256;
TL0 = 0xef; 或者 TL0 = (65535 - 10000) % 256;
3、定時/計數器相關的寄存器
與定時/計數器相關的寄存器除了計數初值寄存器THx和TLx之外,就是TMOD寄存器和TCON寄存器,務必掌握。
<1> TMOD模式控制寄存器,不能進行位尋址,只能字節操作。
<2> TCON中斷標志寄存器,參考【藍橋杯單片機07】
4、定時/計數器的編程思路
在定時/計數器的程序設計中,通常有兩個函數:初始化函數和中斷服務函數。
在初始化函數中,一般需要進行以下幾個配置:
<1> 配置工作模式,即對TMOD寄存器編程。
<2> 計算技術初值,即對THx和TLx寄存器進行賦值。
<3> 使能定時/計數器中斷,即ET0或ET1置1。
<4> 打開總中斷,即EA =1。
<5> 啟動定時器,即TR0或TR1置1。
在中斷服務函數中,一般需要進行以下的編程:
<1> 如果不是自動重裝模式,需要對THx和TLx重新賦值。
<2> 進行間隔定時到達的邏輯處理(越少越好)。
其程序框架和代碼編寫基本上差不多:
5、單元訓練題目
6、實現源碼參考
#include "reg52.h" sbit HC138_A = P2^5; sbit HC138_B = P2^6; sbit HC138_C = P2^7; sbit LED1 = P0^0; sbit LED2 = P0^1; void Init74HC138(unsigned char n) { switch(n) { case 4: HC138_A = 0; HC138_B = 0; HC138_C = 1; break; case 5: HC138_A = 1; HC138_B = 0; HC138_C = 1; break; case 6: HC138_A = 0; HC138_B = 1; HC138_C = 1; break; case 7: HC138_A = 1; HC138_B = 1; HC138_C = 1; break; case 8: HC138_A = 0; HC138_B = 0; HC138_C = 0; break; } } void Init_Timer0() { TMOD = 0x01; TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; ET0 = 1; EA = 1; TR0 = 1; } unsigned char count = 0; void SeviceTimer0() interrupt 1 { TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; count++; if(count == 10) { LED1 = ~LED1; } if(count == 20) { LED2 = ~LED2; count = 0; } } main() { Init74HC138(4); Init_Timer0(); while(1); }
7、定時器進階強化訓練