|
以前學(xué)了好幾次單片機(jī),都是半途而廢,這次要把基礎(chǔ)打好點(diǎn)才行。
話說定時(shí)器還是很重要的。。。
對(duì)51單片機(jī)來說,其實(shí)定時(shí)器和計(jì)數(shù)器是一樣的東西,下面把它們統(tǒng)稱為定時(shí)器了。
51單片機(jī)有兩個(gè)定時(shí)器,它們的核心是兩個(gè)16位的加1計(jì)數(shù)器T0和T1,它們又被分為兩個(gè)8位的計(jì)數(shù)器TH0,TL0,TH1,TL1。
當(dāng)作為計(jì)數(shù)器使用時(shí),計(jì)數(shù)脈沖來自外部引腳P3.4(T0)和P3.5(T1)。當(dāng)該腳的輸入信號(hào)發(fā)生由高到低的負(fù)跳變時(shí),讀數(shù)器TH、TL的值就加1。
定時(shí)器其實(shí)也是計(jì)數(shù),只不過計(jì)數(shù)的脈沖來源的內(nèi)部時(shí)鐘。
程序是怎樣知道定時(shí)器的時(shí)間到了呢?用中斷啦。。。
定時(shí)器使用的是加法計(jì)數(shù),而且只在計(jì)數(shù)溢出時(shí)才申請(qǐng)中斷,因此,要實(shí)現(xiàn)自定義定時(shí)或計(jì)數(shù),需要自己計(jì)算計(jì)數(shù)的起點(diǎn),并將它們填到TH、TL中。
也就是說,如果我要記1000個(gè)時(shí)鐘脈沖,我就將TH和TL的值設(shè)到距離最大值還差1000的位置。
假設(shè)計(jì)數(shù)的最大值是MAX(工作模式不同,這個(gè)值不同),則起點(diǎn)X的計(jì)算方法如下:
在計(jì)數(shù)方式下,X=MAX-計(jì)數(shù)值
在定時(shí)方式下,X=MAX-定時(shí)值/T,其中T為單片機(jī)的機(jī)器周期。如當(dāng)機(jī)器周期=0.5us時(shí),如果定時(shí)器工作于模式0,MAX = 2^13 * 0.5us = 4.096ms;如果工作于模式1,則最大定時(shí)值為MAX = 2 ^ 16 * 0.5us = 32.768ms。
在注意的是,在溢出后,除了模式2之外,程序都要重新裝入初值!
使用定時(shí)器的步驟:
1. 指定工作模式,即TMOD寄存器;
2. 裝入初始值,即對(duì)TH和TL賦值;
3. 啟動(dòng)定時(shí)器中斷,通過賦值IE和優(yōu)先級(jí)寄存器IP來實(shí)現(xiàn),如果不使用中斷,則忽略此步驟;
4. 啟動(dòng)定時(shí)器,即置位TR0或TR1。
模式0:
此模式為13位計(jì)數(shù)器,使用TH及TL中的低5位組成,此模式主要是為了向前兼容而設(shè)計(jì)的;在此模式下,當(dāng)TL的低5位溢出時(shí),向TH進(jìn)位,當(dāng)TH溢出時(shí),計(jì)數(shù)器清零,同時(shí)TF置1,另外發(fā)出中斷請(qǐng)求。
模式1:
此模式為16位計(jì)數(shù)器,使用TH和TL中的所有位,此模式方便計(jì)算初值,而模式0中要由TH和TL中的5位組成一個(gè)13位的數(shù),麻煩。
模式2:
此模式是8位自動(dòng)重新裝入的計(jì)數(shù)器,其中TH作為計(jì)數(shù)初值寄存器,初值在程序中設(shè)置,程序初始化時(shí),TL=TH,當(dāng)TL溢出時(shí),自動(dòng)設(shè)置TL=TH,重新計(jì)數(shù),TF標(biāo)志置1,TH中的數(shù)不受影響。溢出信號(hào)還將送到串行通信系統(tǒng),產(chǎn)生串口通訊的波特率。
模式3:
此模式是將TL和TH分成兩個(gè)獨(dú)立的計(jì)數(shù)器。T1沒有模式3,只有T0有模式3。如果T0工作在方式3下,那么T1就只能工作在0、1、2方式下,因?yàn)門R1及TF1已經(jīng)被T0借用。
可以通過TMOD和TCON兩個(gè)寄存器控制它們。
TMOD
---------------------------------------------------------
用于T1 | 用于T0
---------------------------------------------------------
GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
TCON
------------------------------------------------------------
用于定時(shí)/讀數(shù)器 | 用于中斷
------------------------------------------------------------
TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
------------------------------------------------------------
TF是溢出的標(biāo)志,TR是運(yùn)行控制位,當(dāng)置TR0=1時(shí),定時(shí)器1即啟動(dòng)。
IT是外部中斷觸發(fā)方式選擇位,0是低電平觸發(fā),1是負(fù)跳變觸發(fā)。
IE是外部中斷請(qǐng)求位。
定時(shí)/計(jì)數(shù)器有四種工作方式,TMOD中的M1和M0即為指定工作方式;
C/T決定是工作于定時(shí)還是計(jì)數(shù)方式;
GATE可控制定時(shí)器的啟動(dòng),當(dāng)GATE=0時(shí),定時(shí)器僅由TR控制,當(dāng)GATE=1時(shí),除TR置1外,還必須等待外部脈沖輸入端P3.4或P3.5有個(gè)高電平,定時(shí)器才能啟動(dòng)。若外部輸入低電平,則定時(shí)器關(guān)閉,這樣可由外部控制定時(shí)器的啟停。
初值計(jì)算舉例(以T0為例):
模式0, 6MHz的晶振,單片機(jī)的機(jī)器周期為12/6MHz=2us=0.002ms,如果要定時(shí)1ms,則有算式:1ms = (2^13-X)*0.002,解出X=7692=0x1E0C,轉(zhuǎn)化為2進(jìn)制為1111000001100,這里面低5位要放到TL中,即TL0=01100=0xC,其余放到TH中,即TH0=11110000=0xF0;
模式1, 12MHz的晶振,單片機(jī)的機(jī)器周期為12/12MHz=1us=0.001ms,如果要定時(shí)10ms,則有算式: 10ms=(2^16-X)*0.001,解出X=55536=0xD8F0,則TH0=0xD8,TL0=0xF0;
模式3, 6MHz的晶振,機(jī)器周期為2us=0.002ms,如果要定時(shí)200us,則有200=(2^8-X)*2,解出X = 156 = 0x9C, 則TL0 = 0x9C
程序舉例:
T0工作于方式1,定時(shí)時(shí)間50ms,輸出周期為1000ms的方波,晶振為11.0592MHz
機(jī)器周期為12/11.0592us,最大值為2^16=65536,X=0x4C00
程序如下:
#include "reg51.h"
sbit P0_1 = P0^1;
char i = 0;
void main()
{
TMOD = 0x01; //T0方式1
TL0 = 0x00; //TL0的初值
TH0 = 0x4C; //TH0的初值
ET0 = 1; //打開定時(shí)器0的中斷允許開關(guān)
EA = 1; //開中斷
TF0 = 0;
TR0 = 1;
while(1);
}
void Int_T0() interrupt 1 using 2
{
TL0 = 0x00; //重新裝入初值
TH0 = 0x4C;
i++;
if (i==10)
{
P0_1 = !P0_1;
i = 0;
}
}
下面這段中斷的程序還須進(jìn)一步研究,呵呵
|
|