文章來源:《51單片機(jī)原理及應(yīng)用(第3版)》5.4節(jié)。
51單片機(jī)采用了自然優(yōu)先級和人工設(shè)置高、低優(yōu)先級的策略。
當(dāng)CPU處理低優(yōu)先級中斷,又發(fā)生更高級中斷時,此時中斷處理過程如下圖所示。
一個正在執(zhí)行的低優(yōu)先級中斷服務(wù)程序能被高優(yōu)先級中斷源的中斷申請所中斷,形成中斷嵌套。
相同級別的中斷源不能相互中斷其服務(wù)程序,也不能被另一個低優(yōu)先級的中斷源所中斷。
如果CPU正在執(zhí)行高優(yōu)先級的中斷服務(wù)子程序,不能被任何中斷源所中斷。

上電時,中斷優(yōu)先級寄存器IP被清零,每個中斷源都處于同一個優(yōu)先級,這時如果其中幾個中斷同時產(chǎn)生中斷請求,則CPU按照片內(nèi)硬件優(yōu)先級鏈路的順序即自然優(yōu)先級響應(yīng)中斷,硬件優(yōu)先級有高到低的順序如下表所示:
| 中斷源 | 默認(rèn)中斷級別 | 中斷號 |
|---|---|---|
| 外部中斷0——INT0 | 最高 | 0 |
| 定時/計數(shù)器0中斷——T0 | 第2 | 1 |
| 外部中斷1——INT1 | 第3 | 2 |
| 定時/計數(shù)器1中斷——T1 | 第4 | 3 |
| 串口中斷——TI/RI | 第5 | 4 |
| 定時/計數(shù)器2中斷——INT2(52獨有) | 第6 | 5 |
如果希望某個中斷源有更高的優(yōu)先級,可以通過設(shè)置中斷優(yōu)先級寄存器IP指定更高優(yōu)先級的中斷。IP各位如下表:
| 位序 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|---|---|---|---|---|---|---|---|---|
| 位名稱 | / | / | / | PS | PT1 | PX1 | PT0 | PX0 |
IP中的某位設(shè)置為,則相應(yīng)的中斷就是高優(yōu)先級;否則就是低優(yōu)先級;在同一個優(yōu)先級下,中斷響應(yīng)的順序和自然優(yōu)先一樣。IP可位尋址。
各個位說明:
-
PS:串口中斷優(yōu)先級控制位 -
PT1:定時器1優(yōu)先級控制位 -
PX1:外部中斷1優(yōu)先級控制位 -
PT0:定時器0優(yōu)先級控制位 -
PX0:外部中斷0優(yōu)先級控制位
比如要求將外部中斷1,定時器0設(shè)為高優(yōu)先級,其它為低優(yōu)先級,那么應(yīng)該置PT0=1,PX1=1,高三位取任意值,設(shè)置為0,那么IP的值應(yīng)該為00000110B=06H,此時如果5個中斷同時發(fā)生,中斷響應(yīng)的次序為:定時器0中斷→外部中斷1→外部中斷0→定時器1→串口中斷。
中斷優(yōu)先級應(yīng)用示例
設(shè)置外部中斷1為高優(yōu)先級,在兩個外部中斷引腳(P3.2和P3.3)接兩個按鍵,P1口連接LED。連接P3.2口的按鍵按下后,LED循環(huán)點亮;連接P3.3口的按鍵按下后,LED全部點亮-熄滅,連續(xù)3次。
Proteus設(shè)計原理電路圖如下:

軟件設(shè)計
源程序清單:
/*
實現(xiàn)功能:中斷優(yōu)先級使用示例,設(shè)置外部中斷1為高優(yōu)先級,P1口連接LED,P3.2和P3.3分別連接兩個按鍵
連接P3.2的按鍵INT0按下后LED循環(huán)點亮,連接P3.3的按鍵INT1按下后LED全部點亮-熄滅,閃爍3次。
通過先按下按鍵INT0,然后再按下按鍵INT1可以看到LED依次點亮-全部點亮熄滅閃爍3次-依次點亮,直觀顯示中斷優(yōu)先級的作用。
[2024-01-31] zoya
*/
#include <reg51.h>
#include <intrins.h>
typedef unsigned char uchar;
#define GPIO_LED P1
void delay(uchar c)
{
uchar i,j;
for(;c>0;c--)
{
for(i=0;i<142;i++)
for(j=0;j<2;j++);
}
}
void main()
{
EX0=1; // 外部中斷0允許位
EX1=1; // 外部中斷1允許位
IT0=1; // 定時器0允許位
IT1=1; // 定時器1允許位
EA=1; // 總中斷允許位
IP=0x04; // 中斷優(yōu)先級設(shè)置,外部中斷1高優(yōu)先級
GPIO_LED=0xff;
while(1);
}
void Int0() interrupt 0
{
uchar i, tmp;
EX0=0; // 關(guān)閉外部中斷0,防止執(zhí)行過程中再次發(fā)生中斷
delay(20);
EX0=1; // 開外部中斷0
while(1)
{
tmp=0xFE;
GPIO_LED=tmp;
for(i=0;i<8;i++)
{
tmp=_crol_(tmp,1);
delay(100);
GPIO_LED=tmp;
}
}
}
void Int1() interrupt 2
{
EX1=0; // 關(guān)閉外部中斷1,防止執(zhí)行過程中再次發(fā)生中斷
delay(20);
EX1=1; // 開外部中斷1
GPIO_LED=0x00; delay(100);
GPIO_LED=0xff; delay(100);
GPIO_LED=0x00; delay(100);
GPIO_LED=0xff; delay(100);
GPIO_LED=0x00; delay(100);
GPIO_LED=0xff; delay(100);
}
仿真結(jié)果:
