標題: 6月ST專欄(4)-STM32Cube_FW_F4中RTC_Calendar例程的BUG [打印本頁]
作者: 小融1號 時間: 2017-1-16 15:56
標題: 6月ST專欄(4)-STM32Cube_FW_F4中RTC_Calendar例程的BUG
640.webp.jpg (28.46 KB, 下載次數: 38)
下載附件
2017-1-16 15:45 上傳
前言實時時鐘(RTC)是一個獨立的 BCD 定時器/計數器,用來提供準確的日歷和時間信息。準確性是其重要的指標。
問題某客戶在其產品的設計中,使用了 STM32F429IIT6。客戶在使用過程發現一個問題,雖然已經有使用電池對 VBAT 進行供電, 但是在經常頻繁的 VDD 上下電之后,發現時鐘會比準確的時間慢幾秒鐘。
融創芯城PCB\PCBA自動報價系統上線啦,各位做電子產品的朋友,歡迎訪問比價、訂購
調研
1.了解問題向客戶了解其使用的固件庫,得知他的程序是參考 STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC 中的 RTC_Calendar 例程。于是找來 STM32439I-EVAL2 來進行驗證,測試發現,STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC 中的 RTC_Calendar 例程確實存在頻繁上下電會導致時間變慢的情況;而對標準外設庫 STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Project\STM32F4xx_StdPeriph_Examples\RTC 中的RTC_Calendar 例程進行測試,則不存在此問題。所以,懷疑 STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC 中的 RTC_Calendar 例程存在 Bug。
2.問題分析仔細閱讀
STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC 中的 RTC_Calendar 例程,分析一下 main.c 主程序,
“if(HAL_RTCEx_BKUPRead(&RtcHandle, RTC_BKP_DR0) != 0x32F2)”是用來判斷 RTC 是否是已經被配 置過的,所以懷疑的重點可放在這之前的“if(HAL_RTC_Init(&RtcHandle) != HAL_OK)”中的 HAL_RTC_Init()函數。
進入位于 stm32f4xx_hal_rtc.c 中的 HAL_RTC_Init()函數,再進入其調用的位于 stm32f4xx_hal_msp.c 中的
HAL_RTC_MspInit()函數,在這個函數中,可以看到以下代碼:
/*##-1- Configue LSE as RTC clock soucre ###################################*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_OFF;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
} |
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
} |
這段代碼中由于選中了 LSE,在其所調用的 HAL_RCC_OscConfig()中對 LSE 進行了重新配置。在 stm32f4xx_hal_rcc.c 中找到 HAL_RCC_OscConfig()函數,發現其對 LSE 重新配置的時候,對 LSE 進行關閉,然后再配置。
到此,回來再看 main.c,由于
“if(HAL_RTC_Init(&RtcHandle) != HAL_OK)”位于 “if(HAL_RTCEx_BKUPRead(&RtcHandle, RTC_BKP_DR0) != 0x32F2)”之前,從程序流程來看,每次 VDD 上電,都會進 行一次 HAL_RTC_Init(),也就是說,每次上電都會有一個關閉 LSE 再打開的動作,這個動作多了,時間變慢的現象就變得很 明顯了。
3.問題解決問題原因很明顯了,那么解決辦法也很簡單,只需要將 HAL_RTC_Init()這個初始化函數挪到判斷 RTC 是否是已經被配置過的 if…else…語句里邊就行了。如果是RTC 已經被配置過的,就不需要再重新初始化一次了。如下:
/*##-1- Configure the RTC peripheral #######################################*/
RtcHandle.Instance = RTC;
/*##-2- Check if Data stored in BackUp register0: No Need to reconfigure RTC#*/
/* Read the BackUp Register 0 Data */
if(HAL_RTCEx_BKUPRead(&RtcHandle, RTC_BKP_DR0) != 0x32F2)
{
/* Configure RTC prescaler and RTC data registers */
/* RTC configured as follow:
- Hour Format = Format 24
- Asynch Prediv = Value according to source clock
- Synch Prediv = Value according to source clock
- OutPut = Output Disable
- OutPutPolarity = High Polarity
- OutPutType = Open Drain */
RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
RtcHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
RtcHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if(HAL_RTC_Init(&RtcHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/* Configure RTC Calendar */ |
RTC_CalendarConfig();
}
else
{
/* Check if the Power On Reset flag is set */
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET)
{
/* Power on reset occured: Turn LED2 on */
BSP_LED_On(LED2);
}
/* Check if Pin Reset flag is set */
if(__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET)
{
/* External reset occured: Turn LED4 on */
BSP_LED_On(LED4);
}
/* Enable the PWR clock */
__PWR_CLK_ENABLE();
/* Allow access to RTC */
HAL_PWR_EnableBkUpAccess();
/* Wait for RTC APB registers synchronisation */
if(HAL_RTC_WaitForSynchro(&RtcHandle) != HAL_OK)
{
/* synchronisation Error */
Error_Handler();
}
/* Clear the RTC Alarm Flag */
__HAL_RTC_ALARM_CLEAR_FLAG(&RtcHandle,RTC_FLAG_ALRAF);
/* Clear the EXTI Line 17 Pending bit (Connected internally to RTC Alarm) */
__HAL_RTC_EXTI_CLEAR_FLAG(RTC_EXTI_LINE_ALARM_EVENT);
/* Clear Reset Flag */
__HAL_RCC_CLEAR_RESET_FLAGS();
} |
結論由于
STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC 中的 RTC_Calendar 例程沒有注意到HAL_RTC_Init()函數里邊會有關閉 LSE 的動作,而每次上電都會運行這個函數,每次上電都會導致時間變慢,上電的次數多了,變慢就很明顯了。所以,例程上是有 Bug 的,需要進行修復。
處理需要將 HAL_RTC_Init()這個初始化函數的位置做個修改。如果 RTC 未被配置過,則進行配置;如果是已經被配置過的,就不需要再重新初始化一次了。標準外設庫 STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Project\STM32F4xx_StdPeriph_Examples\RTC 中的 RTC_Calendar 例程是沒有問題的,參考此例程,修改得一基于 STM32Cube_FW_F4 的 RTC_Calendar 例程,見附件。
建議上電時對 LSE 進行重新初始化可能會導致 RTC 計時不準確,所以在實際應用過程中應該對此注意一下。
文章來源:微信公眾號 融創芯城(一站式電子元器件、PCB、PCBA購買服務平臺,項目眾包平臺,方案共享平臺)
歡迎光臨 (http://www.zg4o1577.cn/bbs/) |
Powered by Discuz! X3.1 |
主站蜘蛛池模板:
奇米超碰在线
|
欧美v免费
|
国产精品一区一区
|
在线免费激情视频
|
亚洲精品久久久9婷婷中文字幕
|
成人免费观看视频
|
国产亚洲精品一区二区三区
|
亚洲成人毛片
|
天堂视频一区
|
日日干日日色
|
久久99一区二区
|
91久久综合
|
午夜欧美a级理论片915影院
|
日日干夜夜操
|
亚洲精品久久久久久久久久久久久
|
国产精品一区二区电影
|
激情欧美日韩一区二区
|
天天av综合
|
亚洲天堂一区二区
|
狠狠伊人
|
九九99精品
|
草草视频在线观看
|
狠狠入ady亚洲精品经典电影
|
久久免费看
|
亚洲专区在线
|
蜜桃精品噜噜噜成人av
|
日韩午夜影院
|
午夜久久久
|
国产精品成人在线
|
国产成人av在线播放
|
av手机免费在线观看
|
久久久久国产精品一区二区
|
精品国产一二三区
|
鲁视频|
免费一级片
|
亚洲精品久久久久久一区二区
|
337p日本欧洲亚洲大胆鲁鲁
|
久久精品国产精品青草
|
成人一区二区三区在线
|
99精品电影
|
成人免费精品视频
|