
在實際的單片機開發中中斷系統是連接硬件事件與軟件響應的核心橋梁。無論是按鍵觸發、定時器溢出還是串口接收到數據都需要通過中斷機制來確保CPU能夠及時響應而無需持續輪詢。對于學習單片機匯編語言的同學而言中斷系統既是課程的重點也是期末考試的必考難點。它涉及中斷源、中斷向量、中斷允許控制、中斷優先級、現場保護與恢復等一系列緊密關聯的概念任何一個環節理解不到位都可能導致程序運行異常。本文將以典型的8051系列單片機為背景深入講解中斷系統的完整工作機制。我們將從最基本的中斷概念入手逐步拆解中斷響應的全過程并結合具體的匯編代碼示例演示如何編寫中斷服務程序。更重要的是我們將針對常見的考點和易錯習題進行剖析幫助你不僅理解原理更能應對考試和實際編程中的問題。通過本文你將掌握中斷系統的配置流程、中斷服務程序的編寫規范并學會排查中斷不響應、中斷嵌套混亂等典型問題。1. 理解中斷系統從硬件事件到軟件響應中斷的本質是一種硬件觸發的機制它允許CPU暫停當前正在執行的程序轉而去處理一個更緊急的事件處理完畢后再返回原程序繼續執行。這個過程類似于你在看書時電話鈴響了你標記下當前的閱讀位置保護現場去接電話執行中斷服務程序接完電話后再回來從標記的位置繼續看書恢復現場。1.1 中斷系統的核心組件在8051單片機中中斷系統主要由以下幾個部分構成中斷源能夠產生中斷請求信號的來源。8051通常有5個固定的中斷源INT0外部中斷0由P3.2引腳引入。T0定時器/計數器0溢出中斷。INT1外部中斷1由P3.3引腳引入。T1定時器/計數器1溢出中斷。TI/RI串行口中斷包含發送完成(TI)和接收完成(RI)。中斷向量每個中斷源在程序存儲器ROM中都有一個固定的入口地址稱為中斷向量。當某個中斷被響應時CPU會自動跳轉到對應的中斷向量地址去執行程序。這是中斷服務程序ISR的起點。中斷允許寄存器IE這是一個可編程的寄存器用于控制整個中斷系統的總開關以及每個中斷源的獨立開關。只有相應的中斷允許位被置1該中斷請求才有可能被CPU響應。中斷優先級寄存器IP當多個中斷同時請求時IP寄存器用于設定它們的優先順序。高優先級的中斷可以打斷正在執行的低優先級中斷服務程序實現中斷嵌套。定時器/計數器控制寄存器TCON其中的某些位用于標識外部中斷的觸發方式電平觸發/邊沿觸發以及定時器溢出標志。1.2 中斷響應的完整流程理解中斷響應流程是應對考題的關鍵。整個過程可以分為以下幾個階段中斷請求中斷源事件發生如定時器溢出、外部引腳電平變化相應的中斷請求標志位如TF0、IE0被硬件自動置1。中斷判優如果多個中斷請求同時發生硬件會根據IP寄存器的設置和固定的內部順序INT0 T0 INT1 T1 串口來決定優先響應哪一個。中斷響應如果CPU處于開中斷狀態EA1且該中斷源被允許如EX01則在當前指令執行完畢后CPU響應中斷。硬件自動完成三件事將下一條指令的地址即斷點地址壓入堆棧保護。清除正在響應的中斷源請求標志位對于邊沿觸發的外部中斷和定時器中斷硬件會自動清除對于串口中斷和電平觸發的外部中斷需要軟件手動清除。根據中斷源將程序計數器PC跳轉到對應的中斷向量地址。執行中斷服務程序ISR程序員在中斷向量地址處通常放置一條跳轉指令如LJMP跳轉到實際的中斷處理代碼段。在ISR中首先要做的是保護現場將PSW、ACC等可能被破壞的寄存器壓棧然后執行具體的處理邏輯最后在返回前恢復現場。中斷返回ISR執行到最后一條指令RETI時硬件自動將之前壓棧的斷點地址彈出到PCCPU從而返回到主程序被中斷的地方繼續執行。RETI指令還會通知中斷系統本次中斷處理已結束。2. 環境準備與核心寄存器詳解在動手編寫代碼前必須清楚如何配置控制中斷系統的各個寄存器。這些寄存器的每一位都對應著特定的控制功能。2.1 中斷允許寄存器IE - Interrupt EnableIE寄存器地址為A8H支持位尋址。它控制著中斷的總開關和分開關。位符號地址功能說明7EAAFH總中斷允許控制位。EA1CPU開放所有中斷EA0CPU屏蔽所有中斷。6-AEH保留位。5ET2ADH定時器2中斷允許位8052系列才有。4ESACH串行口中斷允許位。ES1允許串口中斷。3ET1ABH定時器1中斷允許位。ET11允許T1中斷。2EX1AAH外部中斷1允許位。EX11允許INT1中斷。1ET0A9H定時器0中斷允許位。ET01允許T0中斷。0EX0A8H外部中斷0允許位。EX01允許INT0中斷。配置示例若想允許外部中斷0和定時器0中斷需要設置EA1, EX01, ET01。SETB EA ; 打開總中斷開關 SETB EX0 ; 允許外部中斷0 SETB ET0 ; 允許定時器0中斷 ; 或者使用字節操作 MOV IE, #10000011B ; EA1, EX01, ET012.2 中斷優先級寄存器IP - Interrupt PriorityIP寄存器地址為B8H支持位尋址。它用于設置5個基本中斷源的優先級默認為0低優先級。位符號地址功能說明7-BFH保留位。6-BEH保留位。5PT2BDH定時器2優先級8052。4PSBCH串行口中斷優先級。3PT1BBH定時器1中斷優先級。2PX1BAH外部中斷1優先級。3PT0B9H定時器0中斷優先級。0PX0B8H外部中斷0優先級。規則某位設為1對應中斷源為高優先級設為0則為低優先級。當兩個不同優先級的中斷同時請求時先響應高優先級。當兩個相同優先級的中斷同時請求時按內部查詢順序INT0 - T0 - INT1 - T1 - 串口響應。高優先級中斷可以打斷正在執行的低優先級中斷服務程序反之則不能。2.3 定時器/計數器控制寄存器TCONTCON的低4位與外部中斷相關高4位與定時器相關。地址88H支持位尋址。位符號地址功能說明7TF18FH定時器1溢出標志。溢出時硬件置1響應中斷后硬件清0或軟件清0。6TR18EH定時器1運行控制位。軟件置1啟動清0停止。5TF08DH定時器0溢出標志。同TF1。4TR08CH定時器0運行控制位。同TR1。3IE18BH外部中斷1請求標志。檢測到INT1引腳有效信號時硬件置1響應中斷后硬件清0邊沿觸發模式。2IT18AH外部中斷1觸發方式控制。IT11邊沿觸發下降沿有效IT10電平觸發低電平有效。1IE089H外部中斷0請求標志。同IE1。0IT088H外部中斷0觸發方式控制。同IT1。注意對于電平觸發的外部中斷CPU在響應中斷后不會自動清除IE0/IE1標志。因此必須在中斷服務程序中通過撤銷INT0/INT1引腳上的低電平信號來使硬件自動清0否則會引發中斷重復響應。2.4 中斷向量表中斷向量是固定的入口地址。編寫程序時必須將跳轉到實際ISR的指令放在這些地址上。中斷源中斷向量地址ROM說明外部中斷0 (INT0)0003H通常放置LJMP INT0_ISR定時器0 (T0)000BH通常放置LJMP TIMER0_ISR外部中斷1 (INT1)0013H通常放置LJMP INT1_ISR定時器1 (T1)001BH通常放置LJMP TIMER1_ISR串行口 (TI/RI)0023H通常放置LJMP UART_ISR3. 匯編語言中斷編程實戰理解了寄存器我們就可以開始編寫一個完整的中斷程序。我們將以實現一個功能為例利用外部中斷0INT0接按鍵控制一個LED接P1.0的亮滅同時利用定時器0中斷實現約1秒的延時用于LED閃爍的頻率控制。3.1 項目需求與硬件連接分析功能系統上電后LED以1秒為周期閃爍。當按下連接在INT0P3.2引腳上的按鍵時LED狀態立即翻轉亮變滅或滅變亮然后繼續以新的狀態閃爍。硬件假設單片機AT89C51/52或其他兼容8051內核的單片機。LED陽極通過限流電阻接VCC陰極接P1.0。P1.0輸出0時LED亮輸出1時LED滅。按鍵一端接地另一端接INT0P3.2引腳。單片機內部上拉電阻使引腳常態為高電平按鍵按下時變為低電平。晶振假設為12MHz一個機器周期為1μs。3.2 程序結構與初始化代碼首先我們需要進行中斷系統和定時器的初始化。ORG 0000H ; 程序起始地址 LJMP MAIN ; 跳轉到主程序 ORG 0003H ; 外部中斷0向量地址 LJMP EXT0_ISR ; 跳轉到外部中斷0服務程序 ORG 000BH ; 定時器0中斷向量地址 LJMP TIMER0_ISR ; 跳轉到定時器0服務程序 ORG 0030H ; 主程序放在向量區之后 MAIN: MOV SP, #60H ; 設置堆棧指針避開工作寄存器區和位尋址區 LCALL INIT ; 調用初始化子程序 LOOP: SJMP LOOP ; 主循環等待中斷發生 ; 初始化子程序 INIT: ; 1. 初始化LED狀態假設初始為滅 SETB P1.0 ; P1.0輸出高電平LED滅 ; 2. 設置外部中斷0為邊沿觸發 SETB IT0 ; IT01下降沿觸發 ; 3. 配置定時器0為模式116位定時器 MOV TMOD, #01H ; TMOD0000 0001BT0模式1T1模式0未用 ; 4. 計算定時器初值12MHz晶振定時50ms ; 機器周期 12 / 12MHz 1μs ; 定時50ms需要計數次數 N 50000 ; 初值 X 65536 - 50000 15536 3CB0H MOV TH0, #3CH ; 高8位 MOV TL0, #0B0H; 低8位 ; 5. 啟動定時器0 SETB TR0 ; TR01啟動T0 ; 6. 開啟中斷 SETB EX0 ; 允許外部中斷0 SETB ET0 ; 允許定時器0中斷 SETB EA ; 開啟總中斷 RET關鍵點解釋ORG偽指令用于指定后續代碼存放的起始地址。必須將跳轉指令準確放在中斷向量地址上。定時器初值計算是常考考點。模式1是16位計數器最大計數值65536。初值 65536 - 所需計數值。初始化順序先配置觸發方式、定時器模式再賦初值、啟動定時器最后打開中斷允許位。這個順序可以避免意外中斷。3.3 中斷服務程序編寫中斷服務程序需要完成現場保護、核心邏輯處理和現場恢復。; 定時器0中斷服務程序 - 用于產生1秒延時基準 TIMER0_ISR: PUSH ACC ; 保護現場將ACC壓棧 PUSH PSW ; 保護現場將PSW壓棧 ; 重裝定時器初值為下一次50ms定時做準備 MOV TH0, #3CH MOV TL0, #0B0H ; 軟件計數器減1假設R7作為50ms計數器 DJNZ R7, TIMER0_EXIT ; 如果R7不為0跳轉到退出 ; 如果R7為0說明20個50ms到了即1秒 MOV R7, #20 ; 重置軟件計數器為20 CPL P1.0 ; 取反P1.0LED狀態翻轉 TIMER0_EXIT: POP PSW ; 恢復現場PSW出棧 POP ACC ; 恢復現場ACC出棧 RETI ; 中斷返回必須用RETI ; 外部中斷0服務程序 - 響應按鍵立即翻轉LED EXT0_ISR: PUSH ACC PUSH PSW ; 按鍵消抖簡單延時 LCALL DELAY_10MS ; 再次檢測INT0引腳確認是有效按鍵防干擾 JB P3.2, EXT0_EXIT ; 如果P3.2已經是高電平則認為是干擾退出 ; 執行核心功能翻轉LED CPL P1.0 ; 等待按鍵釋放避免一次按下多次觸發 WAIT_RELEASE: JNB P3.2, WAIT_RELEASE ; 如果P3.2還是低電平循環等待 EXT0_EXIT: POP PSW POP ACC RETI ; 一個簡單的10ms延時子程序用于按鍵消抖 DELAY_10MS: MOV R6, #20 D1: MOV R5, #250 DJNZ R5, $ DJNZ R6, D1 RET關鍵點解釋現場保護與恢復中斷可能發生在任何時刻必須保護中斷程序中會用到的所有寄存器如ACC、PSW、B以及通用寄存器Rn。通常使用PUSH和POP指令成對操作。PSW保護了標志位和當前工作寄存器組。定時器中斷在ISR中必須重裝初值否則下次定時會從0開始計數導致定時不準。使用軟件計數器如R7來實現更長的定時如1秒。外部中斷消抖機械按鍵會產生抖動需要在檢測到中斷后延時再判斷避免誤觸發。防干擾與等待釋放JB P3.2, EXT0_EXIT用于排除干擾脈沖。WAIT_RELEASE循環確保按鍵松開后才退出防止一次按下產生多次中斷。中斷返回必須使用RETI指令它除了恢復PC還會通知中斷控制系統該中斷已處理完畢允許響應新的同級或低級中斷。4. 核心考點與典型習題剖析掌握了基本編程后我們針對考試中常見的題型和易錯點進行深入分析。4.1 考點一中斷響應條件與流程判斷常見題型判斷在某種特定條件下如某條指令執行期間某個中斷請求是否會被響應何時響應例題假設CPU正在執行一條MOVX A, DPTR指令訪問外部RAM需2個機器周期此時外部中斷0INT0引腳上出現了一個有效的下降沿IT01。已知EA1EX01且無其他中斷請求。問INT0中斷是否會被響應何時響應分析與解答條件滿足EA和EX0都已打開INT0請求有效滿足中斷響應條件。響應時機CPU會在當前指令執行完畢后去查詢中斷請求標志。MOVX指令需要2個機器周期。因此INT0的中斷請求會在該MOVX指令的第二個機器周期結束時被采樣到并在該指令執行完畢后即下一條指令開始前進入中斷響應周期。答案會被響應。響應發生在MOVX A, DPTR指令執行完畢之后。關鍵記憶點中斷采樣發生在每個指令的最后一個機器周期。響應發生在當前指令執行完下一條指令開始前。長指令如乘除、MOVX執行期間發生中斷也需要等該指令執行完。4.2 考點二中斷優先級與嵌套分析常見題型給定中斷允許和優先級設置分析多個中斷同時或先后發生時的響應順序。例題設置IE 8FH (10001111B) IP 06H (00000110B)。請分析(1) 若INT0和T1中斷同時請求誰先被響應(2) 若CPU正在執行T1的中斷服務程序此時INT0請求中斷會怎樣(3) 若CPU正在執行INT0的中斷服務程序此時T1請求中斷會怎樣寄存器分析IE 10001111BEA1, ES0, ET11, EX10, ET01, EX01。允許INT0、T0、T1中斷。IP 00000110BPX10, PT01, PX00。T0為高優先級INT0和T1為低優先級。解答同時請求INT0和T1同時請求且均為低優先級。此時按內部查詢順序決定。查詢順序為INT0 - T0 - INT1 - T1 - 串口。因此INT0先于T1被響應。T1執行中INT0請求T1為低優先級INT0也為低優先級。同級或低級中斷不能打斷正在執行的中斷服務程序。因此CPU不會響應INT0直到T1的ISR執行完畢返回主程序后才會響應INT0。INT0執行中T1請求同理T1不能打斷INT0。但這里有一個陷阱T1的中斷請求標志TF1在請求時已被置1。雖然本次不能打斷但當INT0執行完RETI返回后CPU會立即檢測到仍有未處理的T1中斷請求因為TF1未被清除并且此時INT0的ISR已結束所以會緊接著響應T1中斷而不會先返回主程序。這種現象看起來像是“連續中斷”。4.3 考點三中斷標志位的清除常見題型分析中斷服務程序中是否需要手動清除中斷標志以及不清除會導致什么問題。例題在電平觸發的外部中斷服務程序中為什么通常需要等待外部信號恢復高電平如果不這樣做可能發生什么分析與解答原因對于電平觸發方式ITx0其中斷請求標志IEx是由外部引腳P3.2/P3.3的低電平直接置位的。CPU響應中斷后硬件不會自動清除IEx標志。只要引腳上低電平持續存在IEx就保持為1。后果如果ISR執行完畢返回后引腳低電平仍然存在CPU會立即再次檢測到有效的中斷請求從而再次進入同一個ISR。這就導致了中斷的重復響應仿佛程序“卡死”在中斷里。解決方案在電平觸發的中斷服務程序中必須確保在返回前外部引腳的低電平信號已消失如等待按鍵釋放。通常通過循環檢測引腳狀態實現如示例代碼中的WAIT_RELEASE部分。對比記憶中斷源觸發方式請求標志清除方式外部中斷0/1邊沿觸發IE0/IE1CPU響應中斷后硬件自動清除。外部中斷0/1電平觸發IE0/IE1硬件不會自動清除。需在ISR中確保外部信號恢復高電平。定時器0/1溢出TF0/TF1CPU響應中斷后硬件自動清除。也可軟件查詢清0。串行口發送/接收TI/RI硬件不會自動清除。必須在ISR中用軟件指令清除CLR TI 或 CLR RI。4.4 考點四現場保護與恢復的細節常見題型給出一個有缺陷的中斷服務程序找出其中現場保護/恢復的錯誤。例題以下定時器中斷服務程序片段有什么問題TIMER_ISR: MOV A, #55H ADD A, R0 MOV R0, A RETI分析與解答 該ISR沒有進行任何現場保護。它直接使用了A累加器、R0寄存器以及R0指向的RAM單元。如果主程序或更高優先級中斷也在使用這些資源中斷返回后這些資源的值已被改變導致主程序運行出錯。正確做法在ISR入口處將要用到的寄存器如ACC, PSW, DPTR, B以及R0-R7壓棧保護在ISR退出前以相反順序出棧恢復。TIMER_ISR: PUSH ACC PUSH PSW PUSH 00H ; 假設R0是0組寄存器其地址為00H ; ... 中斷處理邏輯 ... POP 00H POP PSW POP ACC RETI注意PUSH和POP的操作對象是直接地址。對于工作寄存器R0-R7需要根據當前使用的寄存器組確定其對應的RAM地址00H-07H對應第0組08H-0FH對應第1組以此類推。5. 常見問題排查與調試技巧在實際編程和實驗過程中中斷相關的問題往往比較隱蔽。下面列出常見的問題現象和排查思路。5.1 中斷完全不響應現象按鍵按下LED無反應定時時間到程序無動作。排查清單總中斷開關是否打開檢查EA位是否設置為1。這是最容易被忽略的一步。特定中斷允許位是否打開檢查EX0、ET0等相應位是否設置為1。中斷觸發方式設置是否正確檢查IT0/IT1。如果是邊沿觸發確保信號有下降沿如果是電平觸發確保低電平持續時間足夠長。中斷向量地址是否正確檢查ORG偽指令是否寫錯地址以及跳轉指令LJMP或AJMP是否寫對了中斷服務程序的標號。堆棧空間是否足夠中斷響應和現場保護需要壓棧如果堆棧指針SP初始設置過小可能導致堆棧溢出覆蓋程序數據引發不可預知的錯誤。通常將SP初始化為60H或更高。硬件連接是否正確用萬用表或邏輯分析儀檢查中斷引腳的電平變化是否符合預期。5.2 中斷只響應一次或響應異常現象按鍵第一次按下有效后續無效或者LED瘋狂閃爍不受控制。排查清單中斷標志是否被正確清除這是最常見的原因。對于串口中斷必須用CLR TI或CLR RI在ISR中手動清除標志。對于電平觸發的外部中斷必須在ISR中等待外部信號恢復高電平否則會不斷重復進入中斷。對于邊沿觸發的外部中斷和定時器中斷硬件會自動清除一般無需軟件干預。但如果中斷被禁止EA0或EXx0時發生了中斷請求標志位會被置1并保持直到中斷被允許。這種情況需要在初始化時手動清除可能遺留的標志位CLR IE0等。中斷服務程序執行時間是否過長如果ISR執行時間超過了中斷事件的間隔可能會丟失中斷。例如定時器50ms溢出一次但ISR執行需要60ms那么第二次溢出時CPU還在執行第一次的ISR且由于同級中斷不能嵌套第二次中斷請求可能被忽略。優化ISR代碼或將耗時操作移到主循環。是否存在中斷嵌套沖突檢查IP寄存器設置。如果高優先級中斷的ISR執行時間很長可能會“餓死”低優先級中斷。5.3 現場保護導致的數據錯亂現象主程序中的變量值在中斷發生后莫名其妙地改變。排查清單是否保護了所有被修改的寄存器仔細檢查ISR凡是用到的ACC、PSW、B、DPTR、Rn以及直接地址單元如果主程序也可能使用就必須保護。PUSH和POP是否成對且順序相反必須遵循“先進后出”原則。是否錯誤地改變了工作寄存器組PSW中的RS1和RS0位決定了當前使用哪組R0-R7。如果在ISR中改變了PSW且未妥善保護返回主程序后主程序使用的R0-R7就變成了另一組導致數據錯亂。一個常見的做法是在ISR開始時通過設置PSW切換到一個專用于中斷的寄存器組這樣就不需要保護R0-R7但退出前要恢復原PSW。6. 最佳實踐與擴展方向6.1 中斷編程最佳實踐保持ISR短小精悍中斷服務程序應只處理最緊急、最核心的任務如置標志位、讀數據、清中斷等。復雜的計算、延時、通信等操作應放到主循環中基于標志位來處理。使用軟件標志進行通信ISR與主程序之間通過軟件標志位變量或字節變量來傳遞信息。這是最安全、最清晰的異步通信方式。注意重入問題避免在ISR和主程序中共用非原子操作的全局變量。如果共用應考慮使用關中斷CLR EA和開中斷SETB EA來保護臨界區但關中斷時間要盡可能短。初始化時清除殘留中斷標志在開啟中斷前先清除TCON、SCON中可能殘留的中斷請求標志位避免一開中斷就誤入中斷。合理規劃堆棧空間根據中斷嵌套層數和現場保護的數據量預留足夠的堆棧空間通常SP初始值設為60H或更高。6.2 擴展方向中斷與低功耗設計在許多單片機應用中低功耗是關鍵指標。中斷是實現低功耗休眠-喚醒模式的基石。休眠模式通過執行特定指令如8051的ORL PCON, #01H進入Idle模式CPU停止工作但外設定時器、串口、外部中斷仍可運行。中斷喚醒當使能的中斷事件發生時CPU被喚醒退出休眠模式執行對應的ISR之后繼續執行進入休眠模式指令之后的代碼。編程模式主程序完成初始化后進入循環處理任務 - 進入休眠 - 被中斷喚醒- 處理中斷 - 返回循環。這樣CPU只在有事件需要處理時才工作極大降低了平均功耗。掌握中斷系統不僅是應對考試更是為后續學習更復雜的單片機應用如實時操作系統RTOS的基礎打下堅實基礎。建議在理解本文示例的基礎上嘗試修改代碼實現中斷嵌套、用中斷方式掃描矩陣鍵盤、用中斷方式實現串口數據收發等實驗從而真正融會貫通。