STM32CubeMX Lesson 2 ─ EXTI外部中斷與Debug模式實作

  EXTI(External interrupt/event controller)外部中斷/事件控制器,可以檢測外部輸入訊號的邊緣,針對需求進行中斷服務程式的處理,通常是用於偵測外部數位訊號的變換或是按鈕開關的狀態更動。而中斷與事件的分別在於是否有進入中斷服務程式,中斷主要是偵測到接腳的變化,跳至中斷服務程式進行處理;而事件不會跳至中斷服務程式,而是進行一些周邊電路的改變,例如進行ADC的採樣、DMA的寫入等等。

  下文將以STM32L053R8Tx為示範,並使用意法半導體官方所提供的Nucleo開發板完成該實驗,使用的IDE為Keil uVision5(MDK-ARM),而STM32CubeMX的版本為6.2.1。

  NVIC (Nested vectored interrupt controller)是 ARM Cortex-M 處理器負責處理中斷的巢狀中斷向量控制器,第一次認識他的時候覺得很抽象又很陌生,主要的任務就是管理中斷的優先級,因此EXTI最後會映射到NVIC中進行處理,詳細可以查看官方所提供的Datasheet DM00095744了解。

Lesson1所述,PC13是開發板預設的藍色Push Button,且預設的模式正是EXTI,且使用負緣觸發(Falling Trigger)。在STM32CubeMX中NVIC需打開EXTI的中斷致能。

產生程式碼後可以發現stm32l0xx_it.c最下方多了中斷服務程式(Interrupt Request Handler),該服務程式呼叫了HAL_GPIO_EXTI_IRQHandler函式。

更深入的了解這個函式的使用,則可以對HAL_GPIO_EXTI_IRQHandler點選右鍵,選單中的Go to Definition,查看該函式的原始碼。

發現到該函數確認有中斷來源後,就會清除中斷旗標,並呼叫Callback Function,因此我們需要在main.c的部分新增一個Callback Function,讓中斷觸發時可以呼叫該函數。

因此在main.c中的int main(void)上方有USER CODE BEGIN 0與USER CODE END 0,在這之間插入Callback Function,並判斷該傳入參數是屬於第13的Pin的中斷,透過while迴圈可以避免彈跳導致過快進入函數,更完整的做法應該是呼叫TIMER計時器20ms,這部分會在後面的文章提及,或在main當中新增變數計數,過短的時間不應連續進入中斷服務程式,以避免彈跳造成誤動作。

初學時甚至直接在此加入Delay Function,沒想到直接死機,因此要切記在中斷服務程式中不要加入延遲,也少使用大量迴圈。

/* USER CODE BEGIN 0 */
int count = 30000 ;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == GPIO_PIN_13){
		while(count--);
		count=30000;
		GPIOA->ODR^=(1<<5);
	}
}
/* USER CODE END 0 */

除了燒錄測試功能是否正確外,STM32的SWD也支援線上Debug,因此可以透過Keil邊運行程式邊逐行Debug,也可以直接觀看暫存器的數值,更了解內部的運作與細節。

編譯完成後可以點選上方工具列,有個d字樣放大鏡的icon,可以進入Debug Mode。

進入Debug模式後可以發現Nucleo開發板的LD1雙色LED會進行交替的閃爍。在上方的工具列有個RST字樣的icon,是RESET的意思,右側的按鈕則是RUN,再右邊有個像電路板的icon,則是可以查看每個周邊的暫存器內容,待會可以透過此區來查看GPIOA與GPIOC的暫存器變化。

下方程式碼的行數的左側,有深灰色底的都可以點擊新增中斷點用來查看該點的運行狀態。而右下角的Call Stack + Locals是用來查看變數與函數記憶體的狀態,下方會更詳細的介紹如何使用。

因此我們將中斷點新增於if處,當PC13按鈕按下,負緣觸發中斷服務程式,則會跳到該行停下,與此同時可以打開System Viewer Windows查看GPIOC的IDR暫存器,觀看暫存器的變化。

打開GPIOC的IDR後,按下RUN,則可以查看到ID13是被勾選的,代表當前的PC13是HIGH的狀態。

當我們按下PC13的Push Button後,可以發現程式停止在我們所設定的中斷點,且IDR中的ID13也沒有被勾選了,代表該停止的狀態時PC13是屬於LOW的狀態。

接著我們點選count變數右鍵,將count變數新增至Watch1,用於查看count的變數狀態,同時將System Viewer Windows中GPIOA打開,用於觀看PA5的輸出狀態。

打開GPIOA中的ODR後,可以查看到目前中斷的OD5是沒有倍勾選的,代表示輸出LOW的狀態,同時開發板上的LD2也沒有亮起,若再次按下RUN,則會發現OD5被勾選,呈現HIGH的狀態。並且將Watch 1當中的count點選右鍵,把16進制顯示勾選移除,則會顯示10進制的數值,為30000。

因為我們程式部分僅有寫while(count–),則沒辦法逐一看到count的狀態,因此需退出Debug模式,將中斷點移除,在main的地方寫簡單的變數遞加,則可以實用上查看變數的功能,而該變數需為全域變數。

因此在main上方宣告int number=0;,在while當中新增遞加與延時,並將中斷點設置於Delay函式,將number新增至Watch視窗,則每次按下RUN則可查看number的遞加狀態。

透過以上的教學,可以熟悉如何使用EXTI外部中斷,不論是讀取按鈕或是數位訊號的狀態,都相當重要,也能透過Debug模式查看暫存器與變數的狀態,在關鍵的程式碼插入中斷點,對於除錯是相當有幫助的,也可以自己熟悉看看Debug模式中的逐行運行,可以更了解程式的整體流向與邏輯變化。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *