[STM32] 12-RTC-Alarm_Interrupt
RTC ( Real-Time Clock ) 實時時鐘,是一組獨立計數器可提供系統時間查詢與時間戳記,RTC 也常用於定時功能,本文章介紹 Stm32F103C8T6 的 RTC 鬧鐘功能,藉由 Hardware Abstraction Layer, HAL 函式庫與 Stm32CubeIDE 開發環境的輔助將功能設定與程式撰寫大大簡化。
文章內容
- RTC Alarm Interrupt 鬧鐘中斷
- 實作
- 成果展示
工具與材料
- STM32CubeIDE
- Blue Pill ( STM32F103C8T6 ) 開發板
- ST-LINK v2
- LED 燈 *1
- 220 Ω 電阻 *1
- 麵包板與單芯線
RTC Alarm Interrupt 鬧鐘中斷
RTC 系統可由外接震盪器與內建 RC 震盪器作為時脈輸入,RTC 會默默地維持時間計數。前一篇文章 [STM32] 11-RTC-Second-Interrupt 介紹了 RTC-Seconds_Interrupt 秒中斷,該功能會週期性的產生中斷,RTC-Alarm_Interrupt 鬧鐘中斷顧名思義就是時鐘走到特定時間就會產生中斷,如此便可在特定時間運行特定程序。
RTC 系統方塊圖
由 RTC 系統方塊圖可以了解到外接時脈訊號進入 RTC 後經由 RTC_DIV 分頻得到我們要的計數頻率,32 位元的 RTC_CNT 計數器會持續計數直到溢位,啟用鬧鐘功能並設定 RTC_ALR 若計數器內容與 RTC_ALR 內容相等就會產生鬧鐘中斷,原理不難理解。
系統方塊圖的灰色部分表示系統處於休眠狀態時仍持續運作,從圖中可以了解 RTC_Alarm 可以用來喚醒。
電路圖
實作
本次實驗利用 RTC-Alarm_Interrupt 鬧鐘來點亮位於 PA1 的 LED 燈,當系統時鐘走到鬧鐘設定時間時就會產生中斷並將 LED 燈點亮。透過 Stm32CubeIDE 開發環境與 HAL 函式庫可以讓這項功能輕鬆完成。
一、開啟 STM32CubeIDE 開發環境,建立一個新的專案。
二、選擇微處理器型號,輸入F103C8 可以快速找到,選擇該型號後按下 「Next」鍵。
三、輸入專案名稱後按下「Finish」鍵。
四、來到 系統設定畫面,接下來進行一連串設定。
五、按順序首先設定 SYS ,由於我們是用 ST-Link V2 燒錄器將程式上傳到晶片,所以這邊的 Debug 選項選擇 「Serial Wire」。
六、RCC 時脈源,HSE 與 LSE 皆選擇 「Crystal / Ceramic Resonator」,其中 HSE 是連接開發板上的 8 MHz 震盪器提供系統使用,LSE 連接開發板的 32 Khz 震盪器作為 RTC 時脈源。
七、RTC 將 「Activate Clock Source 」與 「Activate Calendar 」打勾,啟用RTC 時脈與Alarm中斷。RTC_OUT 項目可選擇 「RTC Output on the Tamper pin 」此功能會在 PC13 腳位輸出校正用的時脈,而 Blue Pill 開發板在 PC13 放了一個小 LED 燈所以當 RTC 運作時會發光,我們可藉此得知 RTC 有在運作。
底下的參數設定:
Calendar Time 設定時間,其中 Data Format 可以設定時間以 BCD 或 BIN 二進碼表示,這裡選擇 Binary data format 以二進碼表示,若設定成 BCD 碼在計數時會有問題,具體原因待釐清。
時、分、秒內容讀者可以自行設定,程式上傳到開發板後就會依此時間做為系統當前時間並開始往前計數。
Calendar Date 設定日期,讀者可自行設定。
Alarm_A 鬧鐘時間,由此得知該型號晶片只有一個鬧鐘可以使用。讀者可自行設定,這裡我們將日曆時間與鬧鐘時間設定成相差一分鐘,目的是為了快速看到成果。
八、NVIC 中斷控制將「RTC Alarm Interrupt through EXTI Line 17 」打勾,啟動 Alarm 中斷。
九、設定 PA1 為輸出模式,並將 PA1 取一個別名 「LED 」。點擊 PA1 選擇 「GPIO_Output」,之後在 PA1 上按滑鼠右鍵選擇 「Enter User Label 」輸入 LED 作為 PA1 腳位的別名。
十、Clock Configuration 設定 RTC 時脈源與系統時脈源。RTC 時脈源選擇 「LSE 」外接震盪器 32,768 Hz 訊號,系統時脈選 「HSE 」選擇外接震盪器訊號。
十一、Project Manager 專案管理,這裡不太需要設定,可以看一下專案名稱以及程式碼自動產生的設定是否符合需求即可。
十二、產生程式碼,可以按存檔鍵或是點擊上方 「Project 」=> 「Generate Code 」產生程式碼。
十三、進入程式碼編輯畫面後,左邊顯示本專案所有相關檔案,點開 「Core 」=> 「Src 」找到 「RTC Alarm IRQHandler (void) 」,這個是鬧鐘中斷的進入點,當觸發鬧鐘中斷時就會執行該函式,點擊該函式瞧瞧裏頭賣何藥。
這時候我們會看到 RTC_Alarm_IRQHandler 函式裡面包含一個 「HAL_RTC_Alarm_IRQHandler 」函式,將該函式按住滑鼠左鍵選起來後按滑鼠右鍵選擇 「Open Declaration 」打開該函式。
這裡便是 「 RTC_Alarm_IRQHandler 」函式的內容,我們可以觀察到進入鬧鐘中斷後 「 RTC_Alarm_IRQHandler 」函式會清除鬧鐘中斷旗標並呼叫 「 HAL_RTC_Alarm_EventCallback 」函式,執行完「 HAL_RTC_Alarm_EventCallback 」函式後就表示該中斷程序已經完成了。
將 「 HAL_RTC_Alarm_EventCallback 」函式複製起來,黏貼到 main.c 主程式的 「 USER CODE BEGIN 4 」區塊裡面,寫上觸發鬧鐘中斷時點亮 PA1 上的 LED 燈程式碼。
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET) ;
十四、為了方便觀察變數,將 MX_RTC_Init 初始化 RTC 函式內的三個變數複製起來並設定為註解。往下便可以看到方才設定的日期時間都在此函式裡面,我們也可以在程式碼中更改日期時間,RTC_TimeTypeDef 結構裡面包含時間成員變數,RTC_DateTypeDef 與 RTC_AlarmTypeDef 分別包含日期成員變數及鬧鐘時間。
之後往上找到 「 USER CODE BEGIN PV」將方才的程式碼貼上,並加入一行
RTC_TimeTypeDef gTime ;
作為 Live Expression 觀察用途。
最後,在 While 迴圈鐘加入讀取當前時間的程式碼
HAL_RTC_GetTime ( &hrtc, &gTime, RTC_FORMAT_BIN ) ;
並加入延遲 500 毫秒。
HAL_Delay ( 500 ) ;
到此程式碼完成了。
十五、完成程式碼撰寫後開始編譯程式碼,按下綠色撥放鍵。
此時會出現 debug 相關設定,在 Debugger 項目將 「ST-Link S/N 」打勾,並點擊右方的 「 SCAN 」鈕,此時 ST-Link v2 燒錄器的號碼會出現在空格中。完成後按下 OK 鍵便會開始編譯與上傳程式到開發板中。
十六、這裡我們更進一步利用 Live Express 功能來觀察時間走動。按一下 甲蟲 按鈕進行除錯。
點擊右邊 Live Express 功能,按一下 「 Add new expression」,輸入我們要觀察的變數「 gTime 」當前時間,與 「 sAlarm 」鬧鐘時間。由於兩個都是結構型態因此分別點擊變數左方的小箭頭方便觀察到變數內容。
之後按下 「 Resume」功能按鈕後便可觀察到當前時間是否順利往前計數,當時間走到鬧鐘時間便會觸發鬧鐘中斷並點亮位於 PA1 的 LED 燈。
成果展示
總結
RTC ( Real-Time Clock ) 的 RTC-Alarm_Interrupt 鬧鐘中斷提供了特定時刻執行程序的功能,本文章總結如下:
- RTC 計數時脈有外接震盪器或內部 RC 震盪器以及 HSE 除以 128 等三種來源。
- RTC 時間日期格式可設定為 BCD 或 Binary 二進制,建議使用二進制格式。
- HAL 函式庫將時間日期以結構 ( structure ) 型態包裝,方便管理。
- HAL 函式庫為 RTC 提供了方便的 API s,常用的功能如下:
- HAL_RTC_SetTime 設定時鐘時間。
- HAL_RTC_SetDate 設定時鐘日期。
- HAL_RTC_GetTime 獲得時鐘目前時間。
- HAL_RTC_GetDate 獲得時鐘目前日期。
- HAL_RTC_SetAlarm 設定鬧鐘時間。
- HAL_RTC_AlarmAEventCallback 鬧鐘中斷回調函式。
感謝讀者
若文章有幫助到您可以拍手給我鼓勵,免費支持我。
相關文章
- [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 [連結]