用Proteus學(xué)習(xí)51單片機(jī)之中斷
以52單片機(jī)來(lái)說(shuō),一共有6個(gè)中斷源,其說(shuō)明如下(序號(hào)用于中斷程序的編寫):
中斷源名稱默認(rèn)級(jí)別序號(hào)說(shuō)明INT0最高0外部中斷0,由P3.2端口線引入,低電平或下降沿引起INT1第32由P3.3端口線引入,低電平或下降沿引起T0第21定時(shí)器/計(jì)數(shù)器0中斷,由T0計(jì)數(shù)器計(jì)滿回零引起T1第43定時(shí)器/計(jì)數(shù)器1中斷,由T1計(jì)數(shù)器計(jì)滿回零引起T2最低5定時(shí)器/計(jì)數(shù)器2中斷,由T2計(jì)數(shù)器計(jì)滿回零引起TI/RI第54串行口中斷,串行端口完成一幀字符發(fā)送/接收后引起中斷的允許和關(guān)閉,由中斷允許寄存器IE控制,而IE又細(xì)分為7位,詳細(xì)控制到每一個(gè)中斷的開關(guān)
位序號(hào)位符號(hào)位地址說(shuō)明D0EX0A8HINT0中斷允許控制D1ET0A9HT0中斷允許控制D2EX1AAHINT1中斷允許控制D3ET1ABHT1中斷允許控制D4ESACH串行口中斷允許控制D5ET2ADHT2中斷允許控制D6----D7EAAFH全局中斷控制,關(guān)閉則所有中斷不可用
說(shuō)明:上表中,都是把某位設(shè)置為1,表示開啟對(duì)應(yīng)的中斷允許,設(shè)0表示關(guān)閉對(duì)應(yīng)的中斷允許,同時(shí),如果要允許任意中斷,首先必須設(shè)置EA為允許
還允許設(shè)置中斷的優(yōu)先級(jí),在中斷優(yōu)先級(jí)寄存器IP中設(shè)置。不過(guò)對(duì)我來(lái)說(shuō),暫時(shí)沒用,就不記錄了,相信到時(shí)候要用的時(shí)候,很容易就能找到對(duì)應(yīng)的信息。
在《教程》中,這一章只說(shuō)了定時(shí)器中斷,所以這里也只寫定時(shí)器中斷,翻了書的目錄,其他中斷在后面,一起來(lái)期待后續(xù)吧。
51單片機(jī)內(nèi)部共有兩個(gè)16位可編程的定時(shí)器,即T0和T1,而52單片機(jī)又加了一個(gè)T2。這些定時(shí)器是單片機(jī)內(nèi)部的獨(dú)立硬件,并不需要耗費(fèi)額外的CPU時(shí)間去幫它們計(jì)時(shí)。當(dāng)定時(shí)器的計(jì)數(shù)器計(jì)滿后,會(huì)產(chǎn)生中斷,從而通知CPU處理中斷。
T0或T1都有兩種模式,定時(shí)模式和計(jì)數(shù)模式,對(duì)于定時(shí)模式來(lái)說(shuō),中斷時(shí)即表示定時(shí)時(shí)間已到,而對(duì)于計(jì)數(shù)模式來(lái)說(shuō),中斷時(shí)表示計(jì)數(shù)值已滿。不管是什么模式,其本質(zhì)都是+1計(jì)數(shù)器,它的計(jì)數(shù)脈沖有兩個(gè)來(lái)源,一是系統(tǒng)的時(shí)鐘振蕩器輸出脈沖經(jīng)過(guò)12分頻后的值;二是由T0或T1的引腳輸入。在計(jì)數(shù)模式時(shí),對(duì)于被計(jì)數(shù)的頻率有一定的要求,即被檢測(cè)的電平,至少要維持一個(gè)機(jī)器周期(即12個(gè)振蕩周期),如當(dāng)晶振頻率為12MHZ時(shí),最高計(jì)數(shù)超過(guò)1/2MHZ。
定時(shí)器(計(jì)數(shù)器)主要由兩個(gè)寄存器控制,即TCON和TMOD。
TMOD各位意義如下:
位序號(hào)D7D6D5D4D3D2D1D0位符號(hào)GATEC/TM1M0GATEC/TM1M0針對(duì)T1針對(duì)T0
說(shuō)明如下:
GATE:門控制位,為0時(shí)表示僅受TCON中的TRX控制,為1時(shí)表由TRX和外部中斷引腳上電平共同控制
C/T:1時(shí)表示計(jì)數(shù)模式,0時(shí)表示定時(shí)器模式
M1和M0:工作方式選擇,如下:
M1M0工作方式00方式0,13位定時(shí)器/計(jì)數(shù)器01方式1,16位定時(shí)器/計(jì)數(shù)器10方式2,8位初值自動(dòng)重裝的8位定時(shí)器/計(jì)數(shù)器11方式3,僅適用于T0,分成兩個(gè)8位計(jì)數(shù)器,T1停止計(jì)數(shù)TCON各位意義如下(后面數(shù)字為1的針對(duì)T1,為0的針對(duì)T0):
位序號(hào)D7D6D5D4D3D2D1D0位符號(hào)TF1TR1TF0TR0IE1IT1IE0IT0說(shuō)明如下:
TFX:定時(shí)器X溢出標(biāo)志位,計(jì)時(shí)器計(jì)數(shù)滿時(shí),該位置1,并申請(qǐng)中斷,進(jìn)入中斷服務(wù)程序后,由硬件自動(dòng)清0.如果使用軟件查詢方式的話,需要手動(dòng)清0
TRX:定時(shí)器X運(yùn)行控制位。GATE=1時(shí),TRX=1且INTX為高電平時(shí),啟動(dòng)定時(shí)器;GATE=0時(shí),TRX=1時(shí)啟動(dòng)定時(shí)器
IEX:外部中斷X請(qǐng)求標(biāo)志。
ITX:外部中斷X觸發(fā)方式標(biāo)志。
------------------------------------------------------------------------
程序以T0的工作方式1,即16位定時(shí)器,設(shè)置GATE=0,此時(shí)計(jì)數(shù)器的運(yùn)行由TR0控制,當(dāng)TR0=1時(shí),計(jì)數(shù)器開始計(jì)數(shù)。由于是16位計(jì)數(shù)器,所以共有65535次計(jì)數(shù),當(dāng)計(jì)數(shù)滿后,還要溢出操作一次,所以當(dāng)觸發(fā)中斷時(shí),共需要65536次。由于中斷需要在計(jì)數(shù)滿時(shí)才會(huì)執(zhí)行,所以如果計(jì)數(shù)不是剛好是65536次的話,必然需要給計(jì)數(shù)器設(shè)置一個(gè)初始值 。比如我們希望計(jì)數(shù)1000次時(shí)觸發(fā)中斷,那么,就要把計(jì)數(shù)器的初始值設(shè)置為65536-1000=64536.由于計(jì)數(shù)器每一個(gè)機(jī)器周期加1,也即12個(gè)時(shí)鐘周期,因此每一個(gè)計(jì)數(shù)代表的時(shí)間是12/f,如12MHZ的晶振,一個(gè)計(jì)數(shù)表示12/12000000=1us。若我們希望產(chǎn)生一次中斷的時(shí)間為t,晶振的頻率為f,則初始值為:
t*f/12 注意單位的一致
比如,我希望1ms產(chǎn)生一次中斷,我的晶振為12MHZ,則初始值為(注意,把1ms換算成0.001s)
0.001*12000000/12 = 1000
由于計(jì)數(shù)器實(shí)際分高8位TH0和TL0(對(duì)應(yīng)T1的就是TH1和TL1了),所以要把初始值的高位存儲(chǔ)在TH0中,而低位存儲(chǔ)在TL0中,仍舊以上面的例子來(lái)說(shuō),則
TH0 = 1000/256 = 3
TL0 = 1000%256 = 232
中斷程序的格式如下:
1//using 工作組不是必須的,暫時(shí)不使用//中斷號(hào)即前面列表中的序號(hào),T0的中斷序號(hào)是1
void 函數(shù)名稱 interrupt 中斷號(hào) using 工作組
{
//程序主體
}
-----------------------------------------------------------------
前置知道介紹完畢,現(xiàn)在編寫程序。本來(lái)想顯示一個(gè)定時(shí)器,顯示在數(shù)碼管上,由于在Proteus上實(shí)現(xiàn)不了數(shù)碼管的連續(xù)顯示(PS:現(xiàn)在我知道了,是可以正常顯示的……,不過(guò)程序就不改了,反正主要是為了說(shuō)清楚中斷和計(jì)時(shí)器),所以就簡(jiǎn)化一下程序,改為L(zhǎng)ED燈亮一秒鐘,滅一秒鐘。由于計(jì)數(shù)器最多能計(jì)65535,即60多ms,所以我們讓它每50ms觸發(fā)一次中斷,這樣20次后,就是一秒了,因此初始值就是15536了。
原理圖:
源程序:
1#include#define uchar unsigned char
#define uint unsigned int
uchar total = 0;
sbit led = P2^0;
//中斷程序,在中斷程序中的操作盡量少,所以把LED之類的操作,放在主函數(shù)中
void T0_time() interrupt 1
{
//每次中斷都執(zhí)行一次初始化,保證每次都是50ms
TH0 = 15536/256;
TL0 = 15536%256;
//中斷一次即把計(jì)數(shù)加1
total++;
}
void main()
{
TMOD = 0x01; //設(shè)置定時(shí)器0,工作方式1
TH0 = 15536/256;//設(shè)置初始值高位
TL0 = 15536%256;//設(shè)置初始值低位
EA = 1;//允許全局中斷
ET0 = 1;//允許定時(shí)器0的中斷
TR0 = 1; //開啟定時(shí)器0
while(1)
{
if(total==20)
{
total=0;
led=~led;
}
}
}