STM32 HAL庫RTC模組列印時間不準的問題
正點原子 STM32F7阿波羅開發板,CubeMx生成工程,使用HAL庫的RTC模組時,發現了列印時間不準的問題,現記錄查證過程。
1、CubeMx的配置反覆查證過,沒有問題。
2、main函式中加入測試程式碼如下:
RTC_DateTypeDef stRtcDate; RTC_TimeTypeDef stRtcTime; if ( (HAL_OK == HAL_RTC_GetDate(&hrtc, &stRtcDate, RTC_FORMAT_BIN)) && (HAL_OK == HAL_RTC_GetTime(&hrtc, &stRtcTime, RTC_FORMAT_BIN)) ) { printf("%d-%d-%d_%d:%d:%d.%d", stRtcDate.Year, stRtcDate.Month, stRtcDate.Date, stRtcTime.Hours, stRtcTime.Minutes, stRtcTime.Seconds, stRtcTime.SubSeconds); }
迴圈執行結果為:
[14:26:18.128]收←◆18-10-22_20:10:10.66
[14:26:19.532]收←◆18-10-22_20:10:10.219
[14:26:20.935]收←◆18-10-22_20:10:10.115
[14:26:22.340]收←◆18-10-22_20:10:10.12
[14:26:23.742]收←◆18-10-22_20:10:10.165
也就是說,定時不準確,大概1秒列印一遍,但列印的時間秒一直不變!
3、經過反覆查證,發現HAL_RTC_GetTime介面的一些注意事項:
/** * @brief Gets RTC current time. * @param hrtc RTC handle * @param sTime Pointer to Time structure with Hours, Minutes and Seconds fields returned * with input format (BIN or BCD), also SubSeconds field returning the * RTC_SSR register content and SecondFraction field the Synchronous pre-scaler * factor to be used for second fraction ratio computation. * @param Format Specifies the format of the entered parameters. * This parameter can be one of the following values: * @arg RTC_FORMAT_BIN: Binary data format * @arg RTC_FORMAT_BCD: BCD data format * @note You can use SubSeconds and SecondFraction (sTime structure fields returned) to convert SubSeconds * value in second fraction ratio with time unit following generic formula: * Second fraction ratio * time_unit= [(SecondFraction-SubSeconds)/(SecondFraction+1)] * time_unit * This conversion can be performed only if no shift operation is pending (ie. SHFP=0) when PREDIV_S >= SS * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values * in the higher-order calendar shadow registers to ensure consistency between the time and date values. * Reading RTC current time locks the values in calendar shadow registers until Current date is read * to ensure consistency between the time and date values. * @retval HAL status */ HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format);
注意最後的note中,“You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values”,也就是說, HAL_RTC_GetTime介面呼叫必須在HAL_RTC_GetDate介面之前!
4、驗證:將程式碼改為:
RTC_DateTypeDef stRtcDate; RTC_TimeTypeDef stRtcTime; if ( (HAL_OK == HAL_RTC_GetTime(&hrtc, &stRtcTime, RTC_FORMAT_BIN)) && (HAL_OK == HAL_RTC_GetDate(&hrtc, &stRtcDate, RTC_FORMAT_BIN)) ) { printf("%d-%d-%d_%d:%d:%d.%d", stRtcDate.Year, stRtcDate.Month, stRtcDate.Date, stRtcTime.Hours, stRtcTime.Minutes, stRtcTime.Seconds, stRtcTime.SubSeconds); }
結果如下:
[14:33:26.200]收←◆18-10-22_20:10:9.16
[14:33:27.602]收←◆18-10-22_20:10:11.169
[14:33:29.006]收←◆18-10-22_20:10:12.65
[14:33:30.409]收←◆18-10-22_20:10:14.218
[14:33:31.812]收←◆18-10-22_20:10:15.115
可見結果正常,如果深入分析兩個介面定義,先讀時間,會鎖存當前時間及日期,再讀出日期,能夠保證日期時間的一致性;若介面呼叫順序反了,則在下次讀時間的時候,會立即再次鎖存時間,因此變化很小。
因此,需要注意呼叫順序。