[STM32] 05-Ext Interrupt
Interrupt 中斷是任何 MCU 系統中必備功能用於事件 Event 的觸發以及對外界的行為監測。本文章介紹以整合開發軟體 STM32CubeIDE 搭配 Hardware Abstraction Layer, HAL 函式庫實現外部中斷功能。
文章內容
- 何謂中斷與事件
- 外部中斷
- 專案需求
- 專案建立與設定
- 使用 HAL 函式庫
- 電路圖
- 成果展示
- 總結
材料
- Blue pill 開發板
- ST-LINK v2 燒錄器
- 麵包板與單芯線
- 按鈕開關 *1
- LED 燈 *1
- 220 Ω 電阻 *1
何謂中斷與中斷事件
想像一個情境,夜幕低垂坐在書桌前翻閱書籍享受美好時光,此時放在床頭的電話響了起來打斷了悠閒氣氛,這時想著會不會是煩人的推銷或是那可愛伊人,最後那輕快的鈴聲告訴自己應該起身接電話耳裡隨即傳來那熟悉的聲音…。
在這個情境中,翻閱文章是當下正在進行的工作,電話響起是個事件而該不該接電話取決於重要性,最後接了電話打斷閱讀。
從這個例子可以理解中斷事件與中斷兩者的關係,中斷事件是指會引發中斷行為的事件而眾多事件也因急迫性有權重差異,中斷則是因中斷事件驅使而進行的工作,那麼所有的事件都會觸發中斷嗎 ? 非也,這要看急迫性與需求我們可以依實際運用決定是否響應事件。
外部中斷
STM32 的中斷方塊圖可以了當我們要使用中斷功能時需要設定一些暫存器,當中斷條件發生時硬體電路會產生訊號來通知觸發中斷了。
對於外部中斷 STM32 提供了邊緣檢測電路可以設定外部觸發訊號是正緣 ( rising edge ) 或是負緣 ( falling edge ) 觸發中斷,此外還需要中斷遮罩與致能 ( enable ) 等設定才會順利運作,這一些設定工作 HAL 函式庫都做好了我們只需要呼叫使用即可,真香 !
外部中斷是由硬體腳位輸入訊號引發的,所以由 EXTI Line 外部中斷線來知道是哪支腳位發出的請求。
專案需求
這一次的專案需求是按下按鈕開關便會點亮或關滅 LED 燈。
- LED 燈與限流電阻接在 PA1 腳位。
- 按鈕開關接在 PA2 腳位,沒外接上拉電阻。
- 按鈕開關觸發外部中斷來控制 PA1 輸出高 / 低 電位使 LED 燈亮滅。
專案建立與設定
- 打開整合開發軟體 STM32CubeIDE 選擇專案目錄後來到歡迎頁面。
- 點擊 Start new STM32 project 新增專案,接下來選擇晶片型號輸入 STM32F103C8 便會出現我們要的晶片型號,點選該型號後按下 「 Finish 」即完成。
- 輸入專案名稱。
- 完成後來到設定頁面。由於 LED 燈接在 PA1 上因此 PA1 設定成 GPIO_Output,按鈕開關接在 PA2 上因為要觸發外部中斷因此要設定成 GPIO_EXTI 2。
為了讓腳位有較好的識別性我們可以為腳位名稱加上別名,在腳位上按滑鼠右鍵選擇 「 Enter User Lable」後填入別名。完成後 I / O 腳位的設定便完成了。
- 接下來進行相關設定。Catagories 項目依序對「SYS」、「RCC」、「GPIO」與 「NVIC」進行設定。
「SYS」設定 Debug ,因為使用 ST-LINK v2 燒錄器所以選擇 Serial Wire 。
「RCC」設定系統時脈來源,Blue Pill 開發板有外接震盪器所以我們可以選擇外接震盪器作為統時脈來源。在 High Speed Clock ( HSE ) 選擇 Crystal / Ceramic Resonator 。
「GPIO」主要對 PA2 腳位設定,由於沒有外接上拉電阻因此需要使用晶片的內部上拉電阻,在 GPIO Pull up / Pull down 選擇 Pull-Up,再來是本文章重點 — 外部中斷,令 PA2 作為外部中斷觸發來源,因為 PA2 採用內部上拉電阻到 +Vcc 因此只有在按下按鈕開關時電位才會改變,所以中斷偵測要設定成 External Interrupt Mode with Falling Edge trigger detection 由高電位降為低電位時觸發中斷。如此 GPIO 的部分就設定好了。
「NVIC」Nested Vectored Interrupt Controller 是中斷中樞,中斷的運作由它掌控。這裡把
EXTI line2 interrupt 的 enable 選項打勾來啟動 PA2 腳位的外部中斷。
接下來在 Clock Configuration 設定系統時脈來源,使用外部震盪器做為時脈來源,在 System Clock Mux 選擇 HSE 。如此便完成。
Project Manager 項目若沒有需要特別設定的則是可以略過。到這裡完成所有設定了。
按下 「Project」==> 「Generate Code」產生預設程式碼後進入到程式撰寫階段。
使用 HAL 函式庫
在程式撰寫頁面可以看到左邊有列出相關的函式庫,找到「 stm32f1xx_it.c 」滑鼠按兩下打開來瞧瞧葫蘆裡有甚麼藥。
「 stm32f1xx_it.c 」是有關於外部中斷的函式庫其內容是層層包裹的,因此使用者呼叫高度抽象化的函式其內部運作是一層呼叫一層來完成對應動作。
我們在「 stm32f1xx_it.c 」找到 「 HAL_EXIT_IRQHandler 」這一條函式,在該函式身上按滑鼠右鍵並選擇「 Open Declaration 」打開另一個函式庫。
開啟後我們發現它是源於「stm32f1xx_hal-gpio.c 」,這裡面有一個函式我們很有興趣
「 void HAL_GPIO_EXIT_Callback ( unit16_t GPIO_Pin )」把它複製起來,原來它就是發生外部中斷後使用者設計後續動作需要用的函式。這就像是中斷服務常式 ISR。
使用 HAL 函式庫「HAL_EXIT_IRQHandler 」函式會檢查中斷旗標是否被設置,若發現中斷旗標被設置了會清除中斷旗標然後呼叫 「HAL_GPIO_EXIT_Callback」執行我們要它做的事。
回到 「main.c 」程式,因為此次專案是藉由按鈕開關觸發外部中斷來點亮或關閉 LED 燈,所以主程式內不需要寫什麼程式敘述,我們只需要把點燈與關燈的程式敘述寫在 HAL_GPIO_EXIT_Callback 這個函式裏頭即可。在 main.c 往下找到 「 USER CODE BEGIN 4」這個區段,把剛才複製來的函式貼過來後只寫一條程式。
其中 HAL_GPIO_TogglePin 用來反覆開關某一 I / O 腳位,每執行一次就會改變狀態因此只要外部中斷一觸發就會點亮或關滅 LED 燈。 HAL_GPIO_TogglePin 有兩個參數,一為腳位所在的 Port ,因為我們把 LED 燈接在 PA1 腳位上所以是 GPIOA,但是我們把 PA1 取了別名 LED 所以這裡要填入 LED_GPIO_Port,若記不住沒關係只要輸入 LED 後按下「 Ctril + 空白鍵」就會跳出相關選項,第二個參數就是腳位名稱同樣的因為取了別名所以填上 LED_Pin。
程式寫好啦 ~
完成程式碼的撰寫後,上方命令列 Project ==> Build All 或是榔頭圖示,建立相關檔案。
相關檔案建立後,按下 RUN 綠色播放鍵圖示。
此時會出現 Debug 設定,Main 項目一般不太需要更改設定。
點選 Debugger ,將 Interface 內的 ST_LINK 前方框框打勾並按下右方的 Scan 按鈕,如果此時ST-LINK v2 燒錄器有接在電腦上就會出現燒錄器 ID 號碼。
設定完成後按下 Run 按鈕就會將程式上傳到 Blue Pill 開發板上頭。
電路圖
成果展示
總結
外部中斷監測 I / O 腳位上的變化若符合條件則觸發中斷,本文章總結如下。
- 外部中斷觸發偵測為 Rising edge 與 Falling edge 兩種。
- Nested Vectored Interrupt Controller , NVIC 掌管中斷功能。
- 發生外部中斷時會執行 HAL_GPIO_EXIT_Callback 函式。
推廣與打賞
感謝讀者
若文章有幫助到您可以拍手給我鼓勵,免費支持我。
相關文章
- [STM32] 00-Install STM32CubeIDE [連結]
- [STM32] 01-ST-LINK [連結]
- [STM32] 02-STM32F103C8T6 [連結]
- [STM32] 03-GPIO-Output [連結]
- [STM32] 04-GPIO-Input [連結]
- [STM32] 05-Ext-Interrupt [連結]
- [STM32] 06-Timer-Basic [連結]
- [STM32] 07-Timer-Interrupt [連結]
- [STM32] 08-Timer-Output_Compare [連結]
- [STM32] 09-Timer-PWM [連結]
- [STM32] 09-Timer-PWM [連結]
- [STM32] 10-Timer-Input_Capture [連結]
- [STM32] 11-RTC-Second-Interrupt [連結]
- [STM32] 12-RTC-Alarm_Interrupt [連結]
- [STM32] 13-Independent_Watch_Dog [連結]
- [STM32] 14-Windows_Watch_Dog [連結]
- [STM32] 15-ADC_Conversion [連結]
- [STM32] 16-ADC_Conversion_Temperature_Sensor [連結]
- [STM32] 17-ADC_Convversion_DMA [連結]
- [STM32] 18-SPI [連結]
- [STM32] 19-UART [連結]
- [STM32] 20-I2C [連結]