【藍橋杯單片機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、定時器進階強化訓練