[STM32] 07-Timer-Interrupt
Timer 計時器提供微處理器計時與計數功能是常用功能之一,利用 Timer 觸發中斷事件比輪詢 ( polling ) 更加方便。本文章將介紹 STM32 Timer 的中斷應用,使用 STM32CubeIDE 作為開發環境並搭配 Hardware Abstraction Layer, HAL 函式庫實現功能需求。
文章內容
- Timer Interrupt 簡介
- HAL 相關函式
- 實作
- 總結
工具與材料
- STM32CubeIDE
- Blue Pill ( STM32F103C8T6 ) 開發板
- ST-LINK v2
- LED 燈 *1
- 220 Ω 電阻 *1
Timer Interrupt 簡介
微處理器的工作程序通常是反覆執行某些任務,計時器中斷可以讓程序不需要反覆檢查時間而是讓時間到了自動告訴微處理器該做什麼動作,就像我們設鬧鐘一樣提醒該做些什麼了不用時時盯著時間。
關於計時器中斷常見作法便是利用「計時器溢位」來達成目的,前面的文章有談到計時器溢位事件我們稍稍複習一下,以上數模式而言計數器會依照時脈訊號的驅動每隔一個週期將計數值加 1 ,直到設定的上限便停止上數而後歸零完成一趟計數週期,在歸零的同時便會觸發計時器上數溢位事件我們可以依據這個事件來設計對應的動作,例如發出聲音或閃燈。
HAL 相關函式
STM32 設定中斷後若發生中斷事件會呼叫 IRQHandler 函式進入中斷程序,我們可以在此程序撰寫發生中斷後要做的事,這裡很特別的是在完成中斷程序後會再呼叫 Callback 函式後才會回到主程式,因此發生中斷會先呼叫 IRQHandler 再呼叫 Callback 一共兩項程序。
我們該把中斷程序放在哪兒呢 ?
答案是,皆可。因為一但進入中斷程序 IRQHandler 與 Callback 都會先後被呼叫。
相關的 HAL 函式:
- HAL_TIM_Start_IT(&htim2) 開啟計時器 Timer2 中斷
- HAL_TIM_IRQHandler(&htim2) Timer2 中斷函式
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 計數器溢位 Callback 函式
實作
這一次我們要利用計時器中斷來點亮與關閉 LED 燈,Blue Pill 開發板的 PA1 腳位上外接一個 LED 燈與限流電阻,設計成點亮 LED 燈隔一秒鐘關閉 LED 燈,如此反覆進行。
相關設定如下:
- I / O 腳位 PA1 設為輸出模式,並取別名為 LED。
- 選用 Timer 2 作為計時器。
- 計時器的時脈頻率設為 72 MHz。
- 計時器的分頻係數設為 36000。
- 計時器計數上限設為 2000。
我們可以計算 72 MHz / 36000 = 2000,得知每 1 / 2000 秒計數器會加 1,經過 2000 次後就是 1 / 2000 * 2000 = 1,因此得到 1 秒鐘完成一次計數週期,接下來計數器會歸零重新計數。
一、打開 STM32CubeIDE 設定專案目錄後來到歡迎頁面。
二、選擇晶片型號,可在搜尋列輸入 F103C8 便會列出我們要的型號。選取晶片型號後按「Next」。
三、輸入專案名稱後按 「Finish 」。
四、 Pinout & Configuration ,滑鼠點一下 PA1 後點選 GPIO_Output設定 PA1 為 GPIO_Output。
接著在 PA1 上按滑鼠右鍵選 Enter User Label 為 PA1 取別名,這裡我們輸入 LED 作為別名。
五、Catagories ,點選 Timers 設定計時器,選用 Timer 2。
在 Clock Source 選用 Internal Clock 。
下方的參數設定,分頻器Prescaler 設 36000–1。Counter Period 設 2000–1。
Catagories ,點選 SYS 設定 Debug 介面,這裡選用 Serial Wire。
Catagories ,點選 RCC 設定 系統時脈來源,在 High Speed Clock ( HSE ) 選 Crystal / Ceramic Resonator。
Catagories ,點選 NVIC 設定中斷,在 TIM2 Global Interrupt 把 Enable 項目打勾。
六、 Clock Configuration 設定時脈來源。
- 下方 PLL Source Mux 選 HSE。
- PLL Mul 案下拉選單,選 9 ,這時時脈來到 8 * 9 = 72 MHz。
- 位於中間的 System Clock Mux 選 PLLCLK 。
- 右邊的 APB1 Prescaler 會變紅色原因是 APB1 連接周邊裝置只能到 36 MHz ,所以我們在 APB1 Prescaler 要按一下下拉選單選 2。
七、Project Manager 的 Project 項目看一下專案目錄與名稱是否正確,一般不需要修改。
Project Manager 的 Generate Code 項目可以選 Copy only the necessary library files。
完成後上方命令列 「Project」==> 「Generate Code」產生預設程式碼。
八、進入程式撰寫頁面後左邊 Project Explore 欄位依序把 core 與 src 目錄展開,在 src 目錄下可以看到 stm32f1xx_it.c 這個檔案掌管中斷,滑鼠在這個檔案上點兩下打開。
打開 stm32f1xx_it.c 後往下找到 void TIM2_IRQHandler(void) 這個函式,裏頭有一個名為
HAL_TIM_IRQHandler(&htim2) 的函式,這個就是 Timer 2 發生中斷後程序就會進來這裡,我們用滑鼠左鍵將 HAL_TIM_IRQHandler 選起來後按滑鼠右鍵,在選單上點選 Open Declaration 會帶我們到 HAL_TIM_IRQHandler(&htim2) 所在檔案。
這時會開啟一個名為 stm32f1xx_hal_tim.h 的檔案,關於 Timer 的相關函式都在這裡,往下找到
Callbacks functions ,這裡有很多 Callback function 這一次要用的是
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
把它選起來後複製到 main.c 主程式底下的 /* USER CODE BEGIN 4 */ 區段內。
我們可以在這裡面撰寫中斷後的程序, 計數器發生溢位中斷後會呼叫HAL_TIM_PeriodElapsedCallback ,我們可以把開關 LED 燈的程式敘述寫在這裡但是要注意的是 Callback 是計時器共用的函式,所以可以加個判斷式只有在 Timer 2 發生中斷才執行。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){if(htim == &htim2)HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);}
不過這時還少了一個動作還沒啟動計時器中斷模式,
在 /* USER CODE BEGIN 2 */ 的地方寫上一段 HAL_TIM_Base_Start_IT(&htim2);
啟動 Timer2 的中斷。
/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(&htim2);/* USER CODE END 2 */
九、完成程式撰寫後按上方命令列 「Project」==> 「Build All」或是按榔頭圖式建立相關檔案。
完成後若沒有錯誤發生可以進行下一步,按上方命令列 「Run」==> 「Run」或綠色播放圖式。
此時會出現 Debug 相關設定,Main 項目列出專案名稱等資訊這裡不需要進行修改。
可以將 ST-LINK v2 燒錄器接上電腦後點選 Debugger ,在 interface 項目上將 ST-LINK S/N 打勾,再按一下右邊的 Scan 按鈕這時會出現 ST-LINK v2 的 ID 號碼。
完成後按下 Apply 與 OK,程式就會傳到開發板上,完成後可以按一下開發板的 Reset 按鈕這時可以看到每隔一秒 LED 燈就會亮滅。
電路圖
成果展示
感謝讀者
若文章有幫助到您可以拍手給我鼓勵,免費支持我。
相關文章
- [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] 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 [連結]