中斷介紹
什么是中斷?
在C語言中是沒有中斷的,一個標准的C語言程序,是從main
函數開始執行的,main
函數退出或者標准庫中定義的一些退出函數被調用,程序也就結束了。對於單片機系統,如果硬件發生了一些事件需要應用程序立即來處理,這就需要用到中斷了。要CPU立即暫停執行即將執行的指令,去執行一些特定的指令,執行完成之后再回到暫停的位置繼續執行,這種機制就叫中斷。
中斷的優勢
- 讓硬件可以把事件通知到軟件,提高了響應的實時性。
- 實現異常處理,提高了系統的穩定性。
- 提高CPU的效率。注意:如果中斷太頻繁,由於頻繁的保存和恢復現場會導致CPU的效率下降。
中斷相關的幾個概念
中斷源
發生中斷的外設,例如定時器事件到了,那么中斷源就是定時器。
全局中斷開關或總中斷
系統中有很多中斷開關,如果需要一次性關閉所有的中斷,那么就需要用全局中斷才行,也就是一個總中斷,可以理解為一個電路的總電源吧。
中斷使能寄存器
控制是否允許產生中斷,也就是這個模塊的中斷開關,使能就是打開的意思,只有打開狀態才允許產生中斷,可以理解為在總電源下面的一個小的支路。
中斷標志
表示是一個外設的那個具體事件發生了,比如說串口UART1,只有一個中斷服務程序,硬件可以產生發送數據完成中斷和接收數據完成中斷,那么需要有個標志在中斷服務程序中讓程序知道具體的事件。
中斷服務程序
當中斷發生的時候要執行的函數,通常需要擴展的語法來編寫。
中斷優先級
如果CPU當前在執行低優先級的中斷,這時候有高優先級的中斷發生了,那么CPU會保存當前上下文環境,去執行高優先級的中斷服務程序,高優先級的執行完之后會返回來繼續執行低優先級的中斷服務程序。直到所有的中斷服務程序都執行完了,才會返回到原來被中斷的位置繼續執行。
寄存器分析
中斷優先級
根據下圖,可以看出,中斷被分為了5組,有4個優先級,IP1_xx
是優先級的高位,IP0_xx
是優先級的低位。
所有的中斷源
根據下圖可以看出共有18個中斷源。
中斷相關寄存器示意圖
根據圖片可以看出,外部中斷的開關下面幾個寄存器決定:
P0ICON
選擇中斷觸發的邊沿。0表示上升沿觸發(低電平跳變為高電平);1表示下降沿觸發(高電平跳變為低電平)。P0IEN
P0口的引腳中斷開關,配置引腳是否允許觸發中斷。P0IE
P0口中斷開關,配置P0端口的8個引腳是否允許中斷。EA
全局中斷(總中斷)開關。P0IF
P0口的中斷標志,表示P0口是否發生了中斷。P0IFG
中斷標志,表示那個引腳發生了中斷。
具體實現
中斷的初始化
//按鍵中斷配置
PICTL |= 0x01; //P0_1腳下降沿觸發 0表示上升沿觸發,1表示下降沿觸發
P0IEN |= 0x02; //P0_1腳中斷使能
P0IE = 1; //P0端口的中斷使能
EA = 1; //全局總中斷使能
中斷服務函數的實現
//定義中斷服務程序
//打上斷點調試,按下一次按鍵由於抖動會進入多次中斷服務程序
#pragma vector = P0INT_VECTOR
__interrupt void KeyInterrupt(void)
{
if ((P0IFG & 0x02) == 0x02) {
P0IFG &= ~0x02; //清除這個引腳的中斷標志
LED1 = !LED1;
}
//注意:必須在P0IFG標志清除之后再清除
P0IF = 0; //清除P0端口的中斷標志
}
注意事項
- 中斷服務函數中的實現,需要先清除引腳的中斷標志
P0IFG
,然后再清楚端口的中斷標志P0IF
,不然可能發生不可預料的行為(見參考手冊)。 - 不要使用外部中斷來實現按鍵檢測,按鍵抖動會導致多次執行中斷服務程序的。可以在中斷服務程序中打上斷點,測試一下就知道了。