1024手机基地看电影,午夜福利视频导航,国产精品福利在线一区,亚洲欧美日韩另类成人,在线观看午夜日本理论片,成年超爽免费网站,国产精品成人免费,精品动作一级毛片,成人免费观看网站,97精品伊人久久大香蕉

標(biāo)題: 6月ST專欄(4)-STM32Cube_FW_F4中RTC_Calendar例程的BUG [打印本頁(yè)]

作者: 小融1號(hào)    時(shí)間: 2017-1-16 15:56
標(biāo)題: 6月ST專欄(4)-STM32Cube_FW_F4中RTC_Calendar例程的BUG

前言
實(shí)時(shí)時(shí)鐘(RTC)是一個(gè)獨(dú)立的 BCD 定時(shí)器/計(jì)數(shù)器,用來(lái)提供準(zhǔn)確的日歷和時(shí)間信息。準(zhǔn)確性是其重要的指標(biāo)。
   
問(wèn)題
某客戶在其產(chǎn)品的設(shè)計(jì)中,使用了 STM32F429IIT6。客戶在使用過(guò)程發(fā)現(xiàn)一個(gè)問(wèn)題,雖然已經(jīng)有使用電池對(duì) VBAT 進(jìn)行供電, 但是在經(jīng)常頻繁的 VDD 上下電之后,發(fā)現(xiàn)時(shí)鐘會(huì)比準(zhǔn)確的時(shí)間慢幾秒鐘。
  
融創(chuàng)芯城PCB\PCBA自動(dòng)報(bào)價(jià)系統(tǒng)上線啦,各位做電子產(chǎn)品的朋友,歡迎訪問(wèn)比價(jià)、訂購(gòu)
調(diào)研

1.了解問(wèn)題
向客戶了解其使用的固件庫(kù),得知他的程序是參考 STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC 中的 RTC_Calendar 例程。于是找來(lái) STM32439I-EVAL2 來(lái)進(jìn)行驗(yàn)證,測(cè)試發(fā)現(xiàn),STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC   中的 RTC_Calendar   例程確實(shí)存在頻繁上下電會(huì)導(dǎo)致時(shí)間變慢的情況;而對(duì)標(biāo)準(zhǔn)外設(shè)庫(kù) STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Project\STM32F4xx_StdPeriph_Examples\RTC   中的RTC_Calendar   例程進(jìn)行測(cè)試,則不存在此問(wèn)題。所以,懷疑  STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC   中的 RTC_Calendar 例程存在 Bug。
2.問(wèn)題分析
仔細(xì)閱讀
STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC 中的 RTC_Calendar 例程,分析一下 main.c 主程序,
“if(HAL_RTCEx_BKUPRead(&RtcHandle, RTC_BKP_DR0) != 0x32F2)”是用來(lái)判斷 RTC 是否是已經(jīng)被配 置過(guò)的,所以懷疑的重點(diǎn)可放在這之前的“if(HAL_RTC_Init(&RtcHandle) != HAL_OK)”中的 HAL_RTC_Init()函數(shù)。
  
進(jìn)入位于 stm32f4xx_hal_rtc.c 中的 HAL_RTC_Init()函數(shù),再進(jìn)入其調(diào)用的位于 stm32f4xx_hal_msp.c 中的
HAL_RTC_MspInit()函數(shù),在這個(gè)函數(shù)中,可以看到以下代碼:
/*##-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,在其所調(diào)用的 HAL_RCC_OscConfig()中對(duì) LSE 進(jìn)行了重新配置。在 stm32f4xx_hal_rcc.c 中找到 HAL_RCC_OscConfig()函數(shù),發(fā)現(xiàn)其對(duì) LSE 重新配置的時(shí)候,對(duì) LSE 進(jìn)行關(guān)閉,然后再配置。
  
到此,回來(lái)再看 main.c,由于
“if(HAL_RTC_Init(&RtcHandle) != HAL_OK)”位于 “if(HAL_RTCEx_BKUPRead(&RtcHandle, RTC_BKP_DR0) != 0x32F2)”之前,從程序流程來(lái)看,每次 VDD 上電,都會(huì)進(jìn) 行一次  HAL_RTC_Init(),也就是說(shuō),每次上電都會(huì)有一個(gè)關(guān)閉  LSE   再打開(kāi)的動(dòng)作,這個(gè)動(dòng)作多了,時(shí)間變慢的現(xiàn)象就變得很 明顯了。
3.問(wèn)題解決
問(wèn)題原因很明顯了,那么解決辦法也很簡(jiǎn)單,只需要將 HAL_RTC_Init()這個(gè)初始化函數(shù)挪到判斷 RTC   是否是已經(jīng)被配置過(guò)的 if…else…語(yǔ)句里邊就行了。如果是RTC   已經(jīng)被配置過(guò)的,就不需要再重新初始化一次了。如下:
/*##-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();
}
結(jié)論
由于
STM32Cube_FW_F4_V1.3.0\Projects\STM324x9I_EVAL\Examples\RTC 中的 RTC_Calendar 例程沒(méi)有注意到HAL_RTC_Init()函數(shù)里邊會(huì)有關(guān)閉 LSE   的動(dòng)作,而每次上電都會(huì)運(yùn)行這個(gè)函數(shù),每次上電都會(huì)導(dǎo)致時(shí)間變慢,上電的次數(shù)多了,變慢就很明顯了。所以,例程上是有 Bug 的,需要進(jìn)行修復(fù)。

  

處理
需要將  HAL_RTC_Init()這個(gè)初始化函數(shù)的位置做個(gè)修改。如果 RTC  未被配置過(guò),則進(jìn)行配置;如果是已經(jīng)被配置過(guò)的,就不需要再重新初始化一次了。標(biāo)準(zhǔn)外設(shè)庫(kù) STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\Project\STM32F4xx_StdPeriph_Examples\RTC   中的 RTC_Calendar   例程是沒(méi)有問(wèn)題的,參考此例程,修改得一基于 STM32Cube_FW_F4 的 RTC_Calendar 例程,見(jiàn)附件。
建議
上電時(shí)對(duì) LSE 進(jìn)行重新初始化可能會(huì)導(dǎo)致 RTC 計(jì)時(shí)不準(zhǔn)確,所以在實(shí)際應(yīng)用過(guò)程中應(yīng)該對(duì)此注意一下。


文章來(lái)源:微信公眾號(hào)   融創(chuàng)芯城(一站式電子元器件、PCB、PCBA購(gòu)買(mǎi)服務(wù)平臺(tái),項(xiàng)目眾包平臺(tái),方案共享平臺(tái))






歡迎光臨 (http://www.raoushi.com/bbs/) Powered by Discuz! X3.1