1. 外部中斷概述
為什么用外部中斷?
當按鍵按下時,CPU 無需輪詢檢測引腳狀態,而是通過中斷機制立即響應,提高效率,適用于實時性要求高的場景。
關鍵概念
- EXTI (External Interrupt/Event Controller):STM32 的外設,負責管理外部中斷/事件。
- NVIC (Nested Vectored Interrupt Controller):管理中斷優先級和使能。
- GPIO 與 EXTI 的映射:每個 GPIO 引腳對應特定的 EXTI 線(如 PA0、PB0 共用 EXTI0)。
2. 準備工作
- 硬件:STM32 開發板(如 STM32F103C8T6)、按鍵電路(接 GPIO 引腳,如 PA0,按下時拉低/拉高)。
- 軟件:STM32CubeMX、Keil MDK 或 IDE。
- 按鍵消抖:硬件消抖(電容電阻)或軟件消抖(延時檢測)。
3. STM32CubeMX 配置
步驟 1:創建工程
- 打開 CubeMX → 新建工程 → 選擇你的 STM32 型號。
步驟 2:配置 GPIO 為外部中斷模式
- 找到按鍵連接的 GPIO 引腳(如 PA0)。
- 設置 GPIO Mode 為 External Interrupt Mode with Rising/Falling edge trigger(根據按鍵電路選擇觸發邊沿,如下降沿觸發 Falling Edge)。
步驟 3:配置 NVIC
- 在 NVIC 標簽頁中,使能對應的 EXTI 中斷(如 EXTI line0 interrupt)。
- 設置優先級(默認優先級即可,復雜項目需調整)。
步驟 4:生成代碼
- Project → Generate Code → 選擇 IDE 生成代碼。
4. 代碼編寫
關鍵函數解析
- 中斷服務函數:
EXTI0_IRQHandler()
(自動生成,無需修改,調用 HAL 庫處理函數)。 - 回調函數:
HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
,用戶在此編寫中斷邏輯。
示例代碼
// 在 main.c 中重寫回調函數
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {if (GPIO_Pin == KEY_PIN) { // KEY_PIN 需替換為你的引腳(如 GPIO_PIN_0)// 簡單消抖:延時檢測電平是否穩定HAL_Delay(10); // 注意:中斷內慎用延時,實際項目建議用標記位+主循環處理if (HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_PIN) == GPIO_PIN_RESET) {// 執行按鍵操作,如翻轉 LEDHAL_GPIO_TogglePin(LED_GPIO_Port, LED_PIN);}}
}
優化建議
- 避免在中斷內使用延時:改用全局變量標記按鍵狀態,在主循環中處理。
volatile uint8_t key_pressed = 0; // 中斷內修改,主循環檢測void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {if (GPIO_Pin == KEY_PIN) {key_pressed = 1; // 標記按鍵按下} }// 主循環中處理 while (1) {if (key_pressed) {HAL_Delay(50); // 消抖if (HAL_GPIO_ReadPin(...)) {// 執行操作}key_pressed = 0;} }
5. 關鍵注意事項
- GPIO 與 EXTI 線映射:PA0、PB0 等共用 EXTI0,同一時間只能有一個 GPIO 使用 EXTI0。
- 中斷優先級:若系統中有多個中斷,需合理配置 NVIC 優先級。
- 消抖處理:機械按鍵需消抖,防止誤觸發。
- 中斷函數簡潔性:避免在中斷內執行耗時操作(如 printf)。
6. 測試與驗證
- 現象:按下按鍵時,LED 狀態翻轉。
- 調試技巧:
- 在回調函數內設置斷點,觀察是否觸發。
- 使用邏輯分析儀或示波器監測引腳電平變化。
7. 常見問題
- 中斷不觸發:
- 檢查 GPIO 配置模式和觸發邊沿。
- 確認 NVIC 中中斷已使能。
- 檢查硬件連接(按鍵是否接觸良好)。
- 按鍵多次觸發:未消抖或觸發邊沿設置錯誤。
總結
通過外部中斷實現按鍵檢測,能顯著提升系統實時性。掌握 CubeMX 配置和 HAL 庫回調機制后,可擴展至其他外部事件(如傳感器信號、通信事件)。進階學習可探索中斷嵌套、事件模式等。