1 中斷介紹
在我們的日常生活中,經常會遇到這樣的情況:我們正在看書,突然客廳的電話響了,這時往往會停止看書,轉而去接電話,接完電話后又接着看書。這種停止當前工作,轉而去做其他工作,做完后又返回來做先前工作的現象稱為中斷。
所以單片機雖然是個機器,它也有類似的中斷現象,當單片機正在執行某程序時,如果突然出現意外情況,它就需要停止當前正在執行的程序,轉而去處理意外情況,處理完后又接着執行原來的程序。
2 中斷相關概念

圖1 中斷結構圖
(1) 中斷源
要讓 CPU 中斷當前的程序去做其他事情,需要向它發出請求信號,CPU 接收到中斷請求信號后才能產生中斷。讓CPU產生中斷的信號稱為中斷源(又稱中斷請求源)。
51系列單片機的中斷源包括:兩個外部中斷源、兩個定時器/計數器中斷源和一個串行通信口中斷源,如果它們向 CPU 發出中斷請求信號,CPU 就會產生中斷,停止執行當前的程序,轉而去執行指定的程序(又稱中斷服務程序或中斷子程序),執行完后又返回來執行原來的程序。

(2) 中斷的優先級別
單片機內的CPU在工作時,如果一個中斷源向它發出中斷請求信號,它就會產生中斷;如果同時有兩個或兩個以上的中斷源發出中斷請求信號,CPU會怎么辦呢?CPU會先接受優先級別高的中斷源請求,然后再接受優先級別低的中斷源請求。


(3) 中斷處理過程
① 響應中斷請求。當 CPU 正在執行主程序時,如果接收到中斷源發出的中斷請求信號,就會響應中斷請求,停止主程序,開始執行中斷。
② 保護斷點。為了在執行完中斷后能返回主程序,在執行中斷時,會將主程序的下一條指令的地址(又稱斷點地址)保存到數據存儲器(RAM)的堆棧中。
③ 尋找中斷入口地址。保護好斷點后,CPU開始尋找中斷入口地址(又稱矢量地址),中斷入口地址存放着相應的中斷子程序,不同的中斷源對應着不同的中斷入口地址。
④ 執行中斷子程序。CPU尋找到中斷入口地址后,就開始執行中斷入口地址處的中斷子程序。由於幾個中斷入口地址之間只有8個單元空間(表中如0003H~000BH相隔8個單元),較小的中斷子程序(程序只有一兩條指令)可以寫在這里,較大的中斷子程序無法寫入,通常的做法是將子程序寫在其他位置,而在中斷入口地址單元只寫一條跳轉指令,由該指令跳轉到中斷子程序。
⑤ 中斷返回。執行完中斷子程序后,就會返回到主程序,返回的方法是從RAM的堆棧中取出之前保存的斷點地址,然后執行該地址處的主程序,從而返回到主程序。
(4)中斷相關寄存器
(5)中斷響應條件:①中斷源有中斷請求;②中斷源的中斷允許位為 1;③ CPU 開中斷(即 EA=1)。
3 功能要求:外部中斷屬於單片機的內部資源,本實驗所使用的獨立按鍵KEY3和KEY3直接接在單片機開發板P3.2和P3.3,而P3.2和P3.3不僅是普通的IO口,而且還可以作為外部中斷使用。故可以通過按鍵來模擬外部的脈沖信號輸入到外部中斷管腳來觸發外部中斷。要實現的功能是,當按下KEY3可控制LED1指示燈亮滅,按下KEY4可控制LED2指示燈亮滅。
4 原理分析
(1)在中斷結構圖1中,INT0和INT1即為外部中斷0和外部中斷1。
INT0對應的是P3.2口的附加功能,可由IT0選擇其觸發方式(低電平有效或者下降沿有效)。當CPU監測到P3.2引腳上出現有效的中斷信號時,中斷標志IE0置1(單片機自動完成),向申請中斷。
INT1對應的是P3.3口的附加功能,可由IT1選擇其觸發方式(低電平有效或者下降沿有效)。當CPU監測到P3.3引腳上出現有效的中斷信號時,中斷標志IE1置1(單片機自動完成),向申請中斷。
(2)外部中斷寄存器的配置
1)中斷請求標志寄存器 TCON

① IT0(TCON[0]):外部中斷0觸發方式控制位,當IT0=0時,為低電平觸發方式;當IT0=1時,為邊沿觸發方式(下降沿有效);
② IE0(TCON[1]):外部中斷0中斷請求標志位;
③ IT1(TCON[2]):外部中斷1觸發方式控制位,當IT1=0時,為低電平觸發方式;當IT1=1時,為邊沿觸發方式(下降沿有效);
④ IE1(TCON[3]):外部中斷1中斷請求標志位。
2)中斷允許控制寄存器 IE

① EX0(IE[0]):外部中斷0允許位;
② ET0(IE[1]):定時/計數器T0中斷允許位;
③ EX1(IE[2]):外部中斷1允許位;
④ ET1(IE[3]):定時/計數器T1中斷允許位;
⑤ ES(IE[4]):串行口中斷允許位;
⑥ IE[5]
⑦ IE[6]
⑧ EA(IE[7]):CPU中斷允許位,即總允許位。
4 硬件設計
(1)系統框圖


(2)獨立按鍵和LED燈原理圖
5 軟件設計
1 #include "reg52.h" 2 3 typedef unsigned int u16; 4 typedef unsigned char u8; 5 6 //定義輸入、輸出管腳 7 sbit KEY3 = P3^2; //獨立按鍵3控制管腳 8 sbit KEY4 = P3^3; //獨立按鍵4控制管腳 9 sbit LED1 = P2^0; //LED1控制管腳 10 sbit LED2 = P2^1; //LED2控制管腳 11 12 //延時函數,ten_us=1時,大約延時10us 13 void delay_10us(u16 ten_us) 14 { 15 while(ten_us--); 16 } 17 18 //對外部中斷0進行初始化設置 19 void exti0_init(void) 20 { 21 IT0 = 1; //下降沿觸發方式 22 EX0 = 1; //打開INT0的中斷允許 23 EA = 1; //打開總中斷 24 } 25 26 //對外部中斷1進行初始化設置 27 void exti1_init(void) 28 { 29 IT1 = 1; //下降沿觸發方式 30 EX1 = 1; //打開INT1的中斷允許 31 EA = 1; //打開總中斷 32 } 33 34 void main() 35 { 36 exti0_init(); //對外部中斷INT0進行配置 37 exti1_init(); //對外部中斷INT1進行配置 38 while(1) 39 { 40 41 } 42 } 43 44 //外部中斷0中斷函數,中斷號為0 45 void exti0() interrupt 0 46 { 47 delay_10us(1000); //消抖,忽略按下抖動過程 48 if(KEY3==0) //再次判斷按鍵3是否按下 49 LED1 = !LED1; //LED1狀態翻轉 50 } 51 52 //外部中斷1中斷函數,中斷號為2 53 void exti1() interrupt 2 54 { 55 delay_10us(1000); //消抖,忽略按下抖動過程 56 if(KEY4==0) //再次判斷按鍵4是否按下 57 LED2 = !LED2; //LED2狀態翻轉 58 }
6 仿真結果

7 實現現象
當按下按鍵KEY3,指示燈LED1點亮,再按下按鍵KEY3,指示燈LED1熄滅,如次循環。同理,按鍵KEY4控制LED2。
