8051的中斷,主要由IE和IP兩暫存器所控制,其中IE控制允許哪一個中斷,IP決定哪個中斷優先,兩暫存器的功能,分別說明如下 :

IE (中斷致能暫存器,預設值為00000000)

EA

----

ET2

ES

ET1

EX1

ET0

EX0

EA: EA=0, 關閉所有中斷
     EA=1, 允許中斷,是允許哪個中斷,還要由各自位元決定

ET2:致能Timer2中斷(只有8052才有)
ES:致能串列傳輸中斷
ET1:致能Timer1中斷
EX1:致能INT1中斷
ET0:致能Timer0中斷
EX0:致能INT0中斷



例如要設定允許串列傳輸(UART)INT0中斷,只要下達


     MOV    IE,#10010001B   即可
     (C語言寫法 IE = 0x91;)

 

IP(中斷優先權暫存器,預設值為00000000)

----

----

PT2

PS

PT1

PX1

PT0

PX0

 

PET2=1 Timer2中斷高優先權(只有8052才有)
PS=1 串列傳輸中斷高優先權
PT1=1 Timer1中斷高優先權
PX1=1 INT1中斷高優先權
PT0=1 Timer0中斷高優先權
PX0=1 INT0中斷高優先權



例如要設定允許串列傳輸(UART)中斷高優先權,只要下達


     MOV    IP,#00010000B   即可
     (C語言寫法 IP = 0x10;)

中斷向量

8051的IE和IP預設值皆為0,也就是中斷都是預設不啟動的,所以在重置(RESET)時,程式都可以從位址0000開始寫起,但8051為區分是哪一個中斷發生,對每一個中斷,都有其預設的中斷向量,只要中斷發生,就到該位址執行中斷程式,以下表列為各種中斷的中斷向量值。

中斷源
中斷向量位址
IE0(INT0)
0003H
TF0(Timer0)
000BH
IE1(INT1)
0013H
TF1(Timer1)
001BH
RI或TI(UART)
0023H
TF2或EXF2(Timer2)
002BH

為配合中斷程式的執行,程式一開始的寫法就要做適度的修正。

假設程式中要執行串列傳輸(UART)和INT0中斷,主程式則必須要避開位址0003H和0023H,程式必須修改如下

 

        ORG     00H
        JMP     START
        ORG     03H        ;告訴組譯器,以下指令由位址0003H開始放程式
        JMP     INT0_INT   ;位址0003H~0023H長度不夠,放不下幾個指令,建議跳至後面執行
        ORG     23H        ;告訴組譯器,以下指令由位址0023H開始放程式 
        JMP     UART_INT

START:
         :

       主程式
         :


INT0_INT:
         :
        INT0中斷程式
         :


         RETI                    ;INT0中斷程式結束


UART_INT:
         :
        UART中斷程式
         :


         RETI                    ;UART中斷程式結束        
            

 

INT0中斷 範例1(ASM) 範例1(C)

INT0中斷 範例2(ASM) 範例2(C)

INT0與INT1中斷 範例(ASM) 範例(C)

 

此外,中斷在任何時候都可能發生,以上述範例為例,如果中斷程式中會不小心更動了主程式某些暫存器的值,
再回到主程式時,會有錯誤發生。因此,中斷程式在一開始執行時,須先將這些暫存器的值放到堆疊,等中斷程式執行
完,要回到主程式前,再將暫存器值從堆疊中取回。

例如:主程式和中斷程式都有用到累加器A,中斷程式


INT0_INT:
         PUSH     ACC
         :
        INT0中斷程式
         :

         POP     ACC
         RETI                    ;INT0中斷程式結束


此外在主程式和中斷程式都有用到R5~R7,但我們並不能寫PUSH    R7這種指令,PUSH指令只能對一般RAM(00H~7FH)
和SFR(80H~FF)這種一位元組位址動作,因此範例中將中斷程式改用暫存器庫1的R0~R7(其實際位址在一般RAM的
08H~0FH),因為修改暫存器庫需設定PSW暫存器的RS0和RS1,所以在修改前也需將PSW存入堆疊,等執行完再將PSW取
回,這樣回到主程式久可使用原來的暫存器庫。


INT0_INT:
        PUSH    ACC	;將累加器內的值存到堆疊
        PUSH    PSW	;將PSW內的值存到堆疊(因以下2指令會影響到PSW內的值)
        SETB    RS0	;使用暫存器庫1
        CLR     RS1
        
         :
        INT0中斷程式
         :
		
        POP     PSW
        POP     ACC
        RETI


 但這樣修改,又可能使的堆疊內的資料出錯,因8051預設堆疊值為07,他的作法是先加1,再存到該值指定的RAM位址,也
就是會從RAM位址08的地方開始放堆疊資料,此部分與暫存器庫1重疊,因此在主程式要先更改堆疊值,將堆疊資料改放到其他
位址,在範例中,主程式將堆疊指標位址移到6F,堆疊資料將從70H開始放置。

      MOV   SP,#6FH