From Zero To Hero | RTC日曆基礎應用問題分析

RTC,Real_Time Clock,即實時時鐘,在許多電子系統中都能看到實時時鐘的存在。

今天是第6篇分享,《STM32學習筆記》之RTC日曆基礎應用問題分析

每塊STM32內部都集成了一個RTC模塊,是一個獨立的定時器/計數器,具有計數、時鐘和鬧鐘等功能。


STM32 RTC 基礎內容

STM32內部集成的RTC相當於一個TIM,具有計數的功能,但和TIM有一些區別,比如供電來自備份區域,可作為低功耗模式自動喚醒單元等。

STM32的RTC除F1系列不具有BCD寄存器(日曆功能)之外,其他系列的RTC大同小異,本文以F4系列RTC為例進行講述。


1. RTC時鐘源

RTC不具備自己輸出時鐘信號的功能,和TIM一樣由內部,或外部晶振提供時鐘源。

通常是由低速外部晶振(LSE)32.768 kHz,或者低速內部晶振(LSI)提供。內部晶振誤差大,如果要求高精度需使用外部晶振。

當然,還可以使用高速外部晶振(HSE)的分頻信號作為時鐘源,但該時鐘源有最高頻率限制。

From Zero To Hero | RTC日曆基礎應用問題分析

2. RTC日曆

RTC的日曆功能算是一個比較重要的功能,但是在早期的F1系列中不具備該功能,需要結合軟件計算才能實現日期和時間的功能。

除F1系列的RTC自生具備日曆功能,即具有日期、時間、亞秒等於日曆相關的寄存器,只需要直接讀取寄存器即可獲取日曆信息。

同時,系統可以自動將月份的天數補償為 28、 29(閏年)、 30 和 31 天。並且還可以進行夏令時補償。


3. RTC鬧鐘

RTC鬧鐘功能也是一個比較實用的功能,大部分RTC都具有兩個可編程的鬧鐘:鬧鐘A和鬧鐘B。

RTC鬧鐘可產生中斷信號,也可以產生鬧鐘輸出信號。


4. RTC自動喚醒

有的產品需要週期性喚醒,比如間隔5秒喚醒一次休眠的芯片。

RTC自動喚醒由 16 位可編程自動重載遞減計數器生成,通過 WUTE 位可擴展至17位。如果頻率為1Hz,則自動喚醒時間可以 1s 到 36h 左右。

以上是重點知識點,更多細節請查閱芯片對應的參考手冊。


STM32 RTC 參數配置

STM32 的RTC使用比較方便,不像TIM各種複雜的關係,可以通過STM32CubeMX很簡單就能使用RTC的各項功能。

下面以F4、Cube配置日曆為例。


1. 配置時鐘源

From Zero To Hero | RTC日曆基礎應用問題分析

2. 配置分頻值

通過32.768kHz信號得到1Hz分辨率,可參考例程默認分頻配置:

32768/128/256 = 1.

備註:從0開始分頻,所以配置的分頻值需要減一:127 = 128 - 1, 255 = 256 - 1.


3. 初始化時間和日期

通過Cube工具初始化時間、日期以及格式:

From Zero To Hero | RTC日曆基礎應用問題分析

以上就是通過Cbue工具配置的參數,生成的代碼:

<code>

static

void

MX_RTC_Init

(

void

)

{ RTC_TimeTypeDef sTime = {

0

}; RTC_DateTypeDef sDate = {

0

}; hrtc.Instance = RTC; hrtc.Init.HourFormat = RTC_HOURFORMAT_24; hrtc.Init.AsynchPrediv =

127

; hrtc.Init.SynchPrediv =

255

; hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

if

(HAL_RTC_Init(&hrtc) != HAL_OK) { Error_Handler(); } sTime.Hours =

0x0

; sTime.Minutes =

0x0

; sTime.Seconds =

0x0

; sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; sTime.StoreOperation = RTC_STOREOPERATION_RESET;

if

(HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK) { Error_Handler(); } sDate.WeekDay = RTC_WEEKDAY_MONDAY; sDate.Month = RTC_MONTH_JANUARY; sDate.Date =

0x1

; sDate.Year =

0x0

;

if

(HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK) { Error_Handler(); }

if

(HAL_RTCEx_SetWakeUpTimer(&hrtc,

0

, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK) { Error_Handler(); } }/<code>

RTC通過Cube工具配置比較省心,如果使用標準外設庫進行配置,就需要注意很多細節,簡單參考官方提供例程。


STM32 RTC 常見問題

STM32內部RTC模塊應用場景相對簡單,不像TIM有複雜的配置以及關聯性。但使用RTC仍需要注意一些細節問題。


問題一:RTC時間不準

有不少工程師都遇到過RTC計數一天,相差幾秒甚至幾十秒的情況。導致時間不準最根本的原因是時鐘源,還有時鐘分頻值。

低速內部晶振(LSI)的誤差相對較大,特別是溫差變化較大的環境。

還有關於時鐘分頻值,上面已經提到了分頻128,實際配置參數應該為127.

解決辦法:使用更高精度低速外部晶振、校正、軟件配置正確分頻值。


問題二:RTC時鐘配置失敗

RTC的供電來源備份區域電源,操作RTC之前,需要使能後備區域操作。如果沒有這一步操作,你會發現操作低速時鐘、RTC可能會失敗。

當然,出現這種情況,一般是使用標準外設庫配置導致的失敗。

解決辦法:使用Cube工具,或參考官方例程初始化代碼。


問題三:RTC日曆不更新的問題

在我們的RTC應用中,經常有人反映在做日曆數據讀取操作時發現日曆不更新的情形。其實,STM32 RTC的日曆寄存器由兩個組成,為了保證讀取時間點的一致性,先讀時分秒然後讀日期做為一個完整的日曆讀取操作。在讀取TIME【時分秒】後,硬件會將當前日曆數據鎖住,直到DATE【年月日】寄存器被讀取後釋放。否則會遇到讀取日曆時發生數據不更新的情況。

解決辦法:對於RTC日曆的讀取要注意讀取動作的完整性,讀了TIME還要讀取DATE才算一個完整操作,以保持讀取時間的一致性。


分享到:


相關文章: