9.1 中斷系統(tǒng)知識介紹
在單片機中有兩個重要的概念分別叫做中斷、中斷系統(tǒng),那么他們分別又代表什么意義呢?當(dāng)單片機CPU正在運行主程序時外界發(fā)生了緊急事件請求,要求單片機停止當(dāng)前的工作,而去處理這個緊急事件,處理完成之后,在回到主程序原來的地方繼續(xù)執(zhí)行,這樣的過程稱之為中斷,實現(xiàn)中斷功能的部件稱為中斷系統(tǒng)。
一般單片機中都有多個中斷源,當(dāng)多個中斷源同時發(fā)出請求的時候,單片機應(yīng)該先響應(yīng)哪一個呢?在單片機中可以設(shè)置中斷源的優(yōu)先級,同時出現(xiàn)時單片機將優(yōu)先響應(yīng)優(yōu)先級高的中斷源。另外一種情況,當(dāng)單片機CPU正在響應(yīng)某個中斷時,一個更高優(yōu)先級的中斷請求產(chǎn)生了,這是CPU將暫停響應(yīng)當(dāng)前低優(yōu)先級的中斷,轉(zhuǎn)而去響應(yīng)高優(yōu)先級的中斷源,響應(yīng)完成后繼續(xù)處理低優(yōu)先級中斷,之后再回到主程序繼續(xù)運行,這個過程稱之為中斷嵌套。
我們這里舉一個生活中的例子來解釋中斷嵌套的過程。當(dāng)你在家中正在打掃衛(wèi)生的時候,家里電話響了,這時你便會先放下手中的活,然后拿起電話接電話,在打電話的時候有人按門鈴了,這是你暫時先放下電話去開門,開完門之后你接著拿起電話繼續(xù)講,當(dāng)掛斷電話后,你緊接著剛才繼續(xù)打掃衛(wèi)生了。例子中打掃衛(wèi)生相當(dāng)于單片機CPU執(zhí)行的主程序,電話相當(dāng)于低優(yōu)先級的中斷,門鈴相當(dāng)于高優(yōu)先級的中斷。在打電話的時候先去開門相當(dāng)于中斷嵌套。
STC89C52單片機提供了8個中斷請求源,分別為:外部中斷0(INT0)、定時器0中斷,外部中斷1(INT1)、定時器1中斷、串口(UART)中斷、定時器2中斷、外部中斷2(INT2)、外部中斷3(INT3)。8個中斷請求源可以設(shè)置為4個中斷優(yōu)先級,每一個中斷源都可以通過軟件設(shè)置為四級優(yōu)先級的任一級。高優(yōu)先級的中斷可以打斷低優(yōu)先級的中斷,反之則不可。同一優(yōu)先級的中斷同時來臨時,則根據(jù)中斷查詢的順序進行中斷響應(yīng)。
如上表所示,在相同優(yōu)先級內(nèi) ,外部中斷0的查詢次序最高,外部中斷3的查詢次序最低。傳統(tǒng)51系列單片機一般只配置上表所示的前5個中斷源,而且只有兩級中斷優(yōu)先級。傳統(tǒng)51點單片機通過寄存器IP設(shè)置優(yōu)先級,STC89C52通過新增加的寄存器IPH與IP寄存器共同設(shè)置4級優(yōu)先級,與傳統(tǒng)兩級中斷優(yōu)先級完全兼容。我們可以將上述8種中斷源分為3大類:
第一種: 外部中斷(INT0、1、2、3)
第二種: 定時器中斷(Timer0,1,2)
第三種: 串口中斷(UART)
每種類型中斷的使用方式都是相同的,只不過設(shè)置的寄存器不相同罷了。前面第六章講解的就是第二種的定時器0中斷。所有中斷的控制寄存器如下表所示,包括7個八位的寄存器。如下表所示,IP、IPH寄存器在單片機復(fù)位后值均為0,結(jié)合上表可知,在不對這兩個寄存器進行重新設(shè)置時,所有中斷均為優(yōu)先級0。
單片機中斷系統(tǒng)結(jié)構(gòu)圖如下圖所示,每一個中斷都有一個單獨中斷允許開關(guān),INT0開關(guān)為EX0,Timer0為ET0,之后有一個中斷允許總開關(guān)EA,EA關(guān)閉才允許中斷,當(dāng)EA斷開時,所有中斷將被屏蔽。在設(shè)置后中斷后,首先需要允許中斷。這一章我們將重點講解外部中斷的使用。
在C語言編程中,中斷又是怎么來實現(xiàn)的呢?在主程序中首先設(shè)置后中斷的工作方式,然后允許中斷,接著程序執(zhí)行主程序,當(dāng)中斷來臨時,程序跳轉(zhuǎn)到對應(yīng)的中斷子函數(shù)中執(zhí)行相應(yīng)的操作,執(zhí)行完之后繼續(xù)回到主程序。在C語言中,8個中斷源對應(yīng)這8個中斷子程序函數(shù),如下圖所示,將中斷要實現(xiàn)各功能編輯到相應(yīng)的函數(shù)中即可。
如圖9-2所示,前面函數(shù)的名字可以根據(jù)需要進行更改,關(guān)鍵字interrupt x決定了這個行數(shù)屬于哪個中斷,在第六章中講到的定時器0中斷,即Timer0中斷,那么它對應(yīng)的為”interrupt 1”。
9.2 外部中斷應(yīng)用
STC89C52系列單片機對中斷源可開放或屏蔽,是有內(nèi)部的特殊功能寄存器IE(中斷允許寄存器)進行控制的,IE寄存器格式如下:
中斷允許寄存器IE各位功能定義如下表所示:
單片機STC89C52復(fù)位后會將寄存器IE清零,需要有用戶對IE中相應(yīng)的位清“0”或置“1”來實現(xiàn)中斷請求的允許或屏蔽。
傳統(tǒng)51單片機具有兩級中斷優(yōu)先級,可實現(xiàn)中斷嵌套。通過中斷優(yōu)先級寄存器IP可實現(xiàn)優(yōu)先級的控制。IP寄存器格式如下:
中斷優(yōu)先級控制寄存器IP各位功能定義如下表所示:
單片機復(fù)位后,優(yōu)先級控制寄存器IP將清零,即所有中斷請求均為低優(yōu)先級。
TCON寄存器在第六章定時器中斷時講解過,其中寄存器的高5位為與定時器/計數(shù)器相關(guān)的功能位,這里不再贅述。這里介紹與外部中斷相關(guān)的看控制位:
特殊功能寄存器TCON低4位功能介紹:
介紹了各控制寄存器的功能之后,下面我們講解外部中斷的實現(xiàn)。為了便于觀察我們設(shè)計的外部中斷0的功能為:當(dāng)外部中斷0(P3.2)引腳出現(xiàn)下降延時,即設(shè)置為下降沿觸發(fā)模式,進入中斷后流水燈流動一次。在RY-51開發(fā)板中外部中斷0的P3.2引腳與獨立按鍵K19相連接,因此當(dāng)按鍵按下一次給管腳P3.2一個下降沿,即產(chǎn)出一次中斷。實現(xiàn)的功能呢為按下一次按鍵,流水燈流動一次,設(shè)計程序如下:
/*----------------------------------------------------
** 外部中斷0試驗,功能:按下按鍵K19,流水燈流動一次。
----------------------------------------------------*/
#include< reg52.h >
#define uint unsigned int
uint Move = 0;
void main()
{
IT0 = 1; //設(shè)置外部中斷0為下降沿觸發(fā)方式
EX0 = 1; //允許外部中斷0中斷
EA = 1;//開全局中斷
while(1);
}
//外部中斷0中斷函數(shù)
void int0_r(void) interrupt 0
{
P1 = ~(0x01<
將程序下載到單片機中,每按一次按鍵K19觀察流水燈的變化情況。這個例子為外部中斷0的基本寫法,依此類推只要改變相應(yīng)的寄存器設(shè)置,同樣可以對外部中斷1,2,3進行應(yīng)用。
這里講解的只是單個中斷的應(yīng)用,下面我們結(jié)合前面講過的定時器0中斷來看一個中斷嵌套的例子。我們將第8章最后的數(shù)碼管顯示的程序進行稍微的改造,將變量Sec每秒增加一次改為來一次外部中斷增加一次,即相當(dāng)于上面的按鍵按一次Sec增加一次,那么數(shù)碼管顯示的將是按鍵的按下次數(shù)。程序的主要變化如下所示:
/*----------------------------------------------------
** 數(shù)碼管顯示任意數(shù)值
**
** case語句應(yīng)用
----------------------------------------------------*/
#include< reg52.h >
#define uchar unsigned char
#define uint unsigned int
#define FOSC 11059200 //單片機晶振頻率
#define T_1ms (65536 - FOSC/12/1000) //定時器初始值計算
uint count = 0;
uint flag = 0;
uint Move = 0;
uint T_count = 0;
uint Sec = 0;
sbit DU = P2^7;
sbit WE = P2^6;
uchar Buf_LED[8] ={0};
//共陽型(0~9,A,b,C,d,E,F,全亮,全滅),字碼組
uchar code table_D[]={0xC0,0xF9,0xA4,0xB0,
0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,
0xC6,0xA1,0x86,0x8E,
0x00,0xFF};
//位選數(shù)組
uchar code table_W[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xFF,0x00};
void LED_disp(unsigned char Num_DU,unsigned char Num_WE);
void main()
{
TMOD = 0x01; //定時器工作模式配置
TL0 = T_1ms; //裝載初始值
TH0 = T_1ms >>8;
TR0 = 1; //啟動定時器
ET0 = 1; //允許定時器中斷
IT0 = 1; //設(shè)置外部中斷0為下降沿觸發(fā)方式
EX0 = 1; //允許外部中斷0中斷
EA = 1; //開總中斷
while(1) //循環(huán)
{
Buf_LED[7]= Sec%10;
Buf_LED[6]= Sec/10%10;
Buf_LED[5]= Sec/100%10;
Buf_LED[4]= Sec/1000%10;
Buf_LED[0]= 17;
Buf_LED[1]= 17;
Buf_LED[2]= 17;
Buf_LED[3]= 17;
}
}
//定時器0中斷函數(shù)
void timer0() interrupt 1
{
TL0 = T_1ms;//重裝初始值
TH0 = T_1ms >>8;
count++;
if(count >= 2)//每一毫秒進入一次中斷,達到2次則為2ms更新一次數(shù)碼管。
{
count = 0;
switch(flag)
{
case 0:LED_disp(Buf_LED[0],flag++);break;
case 1:LED_disp(Buf_LED[1],flag++);break;
case 2:LED_disp(Buf_LED[2],flag++);break;
case 3:LED_disp(Buf_LED[3],flag++);break;
case 4:LED_disp(Buf_LED[4],flag++);break;
case 5:LED_disp(Buf_LED[5],flag++);break;
case 6:LED_disp(Buf_LED[6],flag++);break;
case 7:LED_disp(Buf_LED[7],flag);flag=0;break;
default:break;
}
}
}
//外部中斷0中斷函數(shù)
void int0_r(void) interrupt 0
{
int i=0;
Sec++;
for( i =0;i<=5000;i++);
}
/*----------------------------------------------------
** 單個數(shù)碼管顯示函數(shù)
**
** Num_DU:顯示的字符
** Num_WE:顯示的位
----------------------------------------------------*/
void LED_disp(unsigned char Num_DU,unsigned char Num_WE)
{
//關(guān)閉所有數(shù)碼管,消隱處理
P0 =table_W[9];
WE = 1;
WE = 0;
//鎖存字符
P0 = table_D[Num_DU];
DU = 1;
DU = 0;
//鎖存位
P0 = table_W[Num_WE];
WE = 1;
WE = 0;
}
如上述代碼所示,增加了外部中斷0特殊功能寄存器的設(shè)置。
將Sec自加放到外部中斷函數(shù)中,并且在函數(shù)中增加了一個延時,讓中斷函數(shù)處理的時間長一點方便中斷嵌套現(xiàn)象的觀察。其它的代碼與數(shù)碼管顯示代碼相同,這里不再贅述。
將程序編譯下載到單片機中,觀察顯示效果。當(dāng)按下一次按鍵K19,數(shù)碼管顯示數(shù)字加1。在觀察現(xiàn)象的時候,能發(fā)現(xiàn)數(shù)碼管顯示會出現(xiàn)閃爍,顯示受到干擾。下面分析一下產(chǎn)生閃爍的原因。
我們在程序中沒有對外部中斷0和定時器0中斷進行中斷優(yōu)先級設(shè)置,所以均為低優(yōu)先級,根據(jù)前面介紹在同一優(yōu)先級條件下外部中斷0的查詢次序高于定時器0中斷,當(dāng)定時器0中斷和外部中斷0同時產(chǎn)生時,將優(yōu)先進入外部中斷0中斷函數(shù)。所以當(dāng)按鍵按下和定時器中斷同時到來時,程序會先進入外部中斷函數(shù),而造成沒有正常的進入定時器中斷刷新數(shù)碼管的顯示,因此數(shù)碼管顯示的閃爍。
那么,在程序中將定時器0中斷設(shè)置為高優(yōu)先級中斷,外部中斷為低優(yōu)先級中斷。因此,當(dāng)定時器中斷到來時,不管程序有沒有正在執(zhí)行外部中斷0函數(shù),程序都會進入到定時器中斷函數(shù)中,保證了數(shù)碼管的刷新,因此消除了數(shù)碼管閃爍的現(xiàn)象,增加的程序代碼如下代碼所示:
void main()
{
TMOD = 0x01; //定時器工作模式配置
TL0 = T_1ms; //裝載初始值
TH0 = T_1ms >>8;
TR0 = 1; //啟動定時器
ET0 = 1; //允許定時器中斷
IT0 = 1; //設(shè)置外部中斷0為下降沿觸發(fā)方式
EX0 = 1; //允許外部中斷0中斷
PT0 = 1;//定時器0設(shè)置為高優(yōu)先級 -----------------增加設(shè)置優(yōu)先級代碼1
PX0 = 0;//外部中斷0設(shè)置為低優(yōu)先級 -----------------增加設(shè)置優(yōu)先級代碼2
EA = 1; //開總中斷
while(1) //循環(huán)
9.3 本章小節(jié)
本章詳細介紹了單片機中斷系統(tǒng)的工作原理以及部分中斷寄存器功能的定義。介紹了外部中斷0功能C語言程序的編寫,介紹了中斷嵌套的應(yīng)用。
-
單片機
+關(guān)注
關(guān)注
6037文章
44562瀏覽量
635913 -
cpu
+關(guān)注
關(guān)注
68文章
10873瀏覽量
212017 -
定時器
+關(guān)注
關(guān)注
23文章
3250瀏覽量
114919 -
中斷系統(tǒng)
+關(guān)注
關(guān)注
1文章
96瀏覽量
61023 -
外部中斷
+關(guān)注
關(guān)注
1文章
131瀏覽量
15831
發(fā)布評論請先 登錄
相關(guān)推薦
評論