1、中斷的概念
對于單片機中斷的概念,我們可以這樣理解:單片機處理某一事件A時,發(fā)生了另一事件B請求(中斷請求);單片機暫時中斷當(dāng)前工作,轉(zhuǎn)去處理事件B(中斷響應(yīng)和中斷服務(wù));待單片機將事件B處理完畢,再回到原來事件A被中斷的地方繼續(xù)處理事件A(中斷返回),這一過程稱為中斷。 引起單片機中斷的根源或原因: 中斷源向單片機提出中斷請求。
2、中斷優(yōu)先級 單片機的中斷系統(tǒng)一般允許多個中斷源,當(dāng)幾個中斷源同時向單片機請求中斷,要求為它服務(wù)的時候,這就存在單片機優(yōu)先響應(yīng)哪一個中斷源請求的問題。通常根據(jù)中斷源的輕重緩急排隊,優(yōu)先處理最緊急事件的中斷請求源,即規(guī)定每一個中斷源有一個優(yōu)先級別。單片機總是先響應(yīng)優(yōu)先級別最高的中斷請求。 中斷優(yōu)先級的三條原則: a:單片機同時接收到幾個中斷時,響應(yīng)優(yōu)先級別最高的中斷請求。 b:正在進(jìn)行的中斷過程不能被新同級或低優(yōu)先級的中斷請求所中斷。 c:正在進(jìn)行的低優(yōu)先級中斷服務(wù),能被高優(yōu)先級中斷請求所中斷。
3、中斷嵌套
當(dāng)單片機正在處理一個中斷請求源的時候(執(zhí)行相應(yīng)的中斷服務(wù)程序),發(fā)生了另外一個優(yōu)先級比它還高的中斷源請求。單片機暫停對原來中斷源的服務(wù)程序,轉(zhuǎn)而去處理優(yōu)先級更高的中斷請求源,處理完以后,再回到原低級中斷服務(wù)程序,這樣的過程稱為中斷嵌套。 4、單片機內(nèi)部中斷電路和寄存器
我們以STC單片機為例進(jìn)行介紹: 上圖是單片機內(nèi)部和中斷有關(guān)的電路,從圖中我們知道單片機可以有5個中斷源,分別是/INT0,T0,/INT1,T1,RX和TX。/INT0和/INT1為外部中斷源;T0和T1為定時器/計數(shù)器中斷;RX和TX為串口收發(fā)中斷。 相關(guān)寄存器有TCON,IE,IP,這些寄存器又是起什么作用的呢: TF1是定時器1的溢出標(biāo)志位,當(dāng)定時器1發(fā)生溢出時,此位變成1,同時提出中斷請求,一直保持到CPU響應(yīng)中斷時,才由硬件清0。如果程序不是采用中斷的方式,而是采用查詢的方式,那么這位需要軟件清0。 TR1是定時器1的運行控制位,當(dāng)它為1時允許定時器1開始計數(shù),為0時禁止定時器1計數(shù)。 TF0和TR0的功能分別與TF1和TR1類似,它們對應(yīng)的是定時器0。 對于IE1,IT1,IEO,IT0的功能在上圖中有描述了,就不多說了。

IE寄存器是中斷允許寄存器,只有相應(yīng)的位置為1了,相關(guān)的中斷才能被允許哦。 IP寄存器是中斷優(yōu)先級控制寄存器,當(dāng)某位被設(shè)成1了,那么對應(yīng)的中斷源就是高優(yōu)先級了哦,就可以中斷低優(yōu)先級中斷源的處理函數(shù)了哦。
好了,今天給大家介紹了單片機內(nèi)部中斷電路和相關(guān)的寄存器,明天給結(jié)合程序給大家講述如何實現(xiàn)單片機中斷功能。
上一條分享我們提到單片機一般有5個中斷源,在這條分享中我們看看如何通過編程實現(xiàn)這些中斷功能。
1、外部中斷
外部中斷源有:INT0和INT1,可由外部信號引發(fā)單片機的中斷,我們需要將信號引到單片機的INT0和INT1管腳上。外部中斷INTO和INT1即可底電平觸發(fā),也可下降沿觸發(fā)。相關(guān)的寄存器有TCON,IE,IP。
下面我們通過一段例程序理解下,怎樣編寫代碼:
#include “reg51.h”
void init_int0(void) //中斷功能的初始化函數(shù),只有對相關(guān)的寄存器進(jìn)行了正確的
配置,采用運用單片機的中斷功能哦。
{
IT0=1; //IT0是寄存器TCON的最低位,在這里設(shè)成1,單片機管腳INT0上的信號低跳變(下降沿)引發(fā)中斷。
EX0=1; //EX0是寄存器IE的最低位,在這里設(shè)成1,允許發(fā)生INT0中斷。
EA=1; //EA是寄存器IE的最高位,在這里設(shè)成1,相當(dāng)于開啟了允許中斷的總開關(guān)。只有EA和EX0都設(shè)成1了, 才開啟了INTO中斷功能哦。
}
void main(void)
{
init_int0(); //需要在主函數(shù)中,對INT0的相關(guān)寄存器進(jìn)行初始化配置的。
while(1);
}
Void exint0() interrupt 0 //中斷函數(shù),把我們希望實現(xiàn)的功能加進(jìn)入,這里面的代碼應(yīng)該盡量簡潔,短 小,以免占用太多的時間哦。
{
加上你希望實現(xiàn)的功能。
}
在看懂上面這段代碼的基礎(chǔ)上大家在想想如果希望是低電平引發(fā)中斷,程序該怎么寫呢?
外部中斷INT1的初始化函數(shù)和中斷處理函數(shù)該怎么寫呢?
2、定時中斷
與定時器/計數(shù)器T0,定時器/計數(shù)器T1中斷相關(guān)的寄存器主要有TMOD,THX,TLX,TCON,IE。下面我們通過一段例程看看怎樣實現(xiàn)定時器/計數(shù)器的中斷功能(以定時器/計數(shù)器0為例)。
#include “reg51.h”
void timer0_init(void)//定時器0中斷初始化函數(shù)
{
TMOD=0x80; //將定時器/計數(shù)器0當(dāng)成13位定時器/計數(shù)器,TL0只用低5位參與分頻,TH0整個8位全用。
TH0=0xXX; //設(shè)定定時器0初始計數(shù)值的高8位
TL0=0xXX; //設(shè)定定時器0初始計數(shù)值的低8位
TR0=1; //定時器0開始計數(shù)
ET0=1; //開定時器0中斷允許
EA= 1; //開總中斷允許
}
void main(void)
{
timer0_init();
while(1);
}
void timer0int interrupt 1
{
TH0=0xXX; //在中斷處理函數(shù)里面記得給TH0重新賦初值哦
TL0=0xXX; //在中斷處理函數(shù)里面記得給TL0重新賦初值哦
加上你希望實現(xiàn)的功能哦。
}
這樣在單片機工作頻率固定的前提下,我們可以通過調(diào)節(jié)TH0和TL0的初值來改變定時0的定時時長,從而改變定時中斷發(fā)生的時間間隔。這樣就以我們希望的時間間隔執(zhí)行中斷處理函數(shù)中的指令。
定時器1的中斷的初始化和定時器0的中斷初始化類似。
需要指出的是定時器0和定時器1有4中不同的工作方式,不同的工作方式的選擇可以通過設(shè)置寄存器TMOD來實現(xiàn)。
3、串口收發(fā)中斷
#include
//FOSC = 11.0592MHz,12T模式,SMOD=0
#define reload_count_1200bps 0xe8
#define reload_count_2400bps 0xf4
#define reload_count_4800bps 0xfa
#define reload_count_9600bps 0xfd
void serial_port_initial(char TH,char TL)
{
SCON=SCON|0x50; //確定串口工作方式,8位可變波特率,無奇偶校驗位
TMOD=TMOD|0x20; //設(shè)置定時器1為8位自動重裝記數(shù)器
PCON=PCON|0x00; //這個寄存器里有一位SMOD,它和波特率的確定有關(guān)。
TH1 = TH; //設(shè)置定時器1自動重裝數(shù)TH1,它和波特率的確定有關(guān)。
TL1 = TL; //設(shè)置定時器1自動重裝數(shù)TL1,它和波特率的確定有關(guān)。
ES=1; //允許串口中斷
EA=1; //開總中斷
TR1=1; //開定時器1
}
波特率=(2SMOD/32)x(定時器1的溢出率) 定時器1的溢出率 = SYSclk/12(256-TH1)
char UARTReceive(void) //串口數(shù)據(jù)接收函數(shù)
{
char ch;
ch=SBUF;
return (ch); // 暫存接收到的數(shù)據(jù)
}
void main(void)
{
serial_port_initial(reload_count_2400bps,reload_count_2400bps);
//初始化串口參數(shù)
while(1);
}
void UART_Interrupr_Receive(void) interrupt 4 //串口接收中斷處理函數(shù)
{
ES = 0;
RI = 0; //當(dāng)串口接收到數(shù)據(jù)時,RI回被置1,同時引發(fā)中斷,在中斷處理函數(shù)中將其清零。
buf = UARTReceive();
ES = 1;
}
好了,今天簡單地和大家分享了一下單片機中斷的一些基本知識,在這里只是簡單地具了幾個例,中斷的用法很有技巧,這需要大家在項目的實踐中去掌握,吃透。
|