本帖最后由 香水城 于 2017-8-16 13:35 编辑
STM32Cube_FW_F4 中RTC_Calendar例程的BUG
前言
实时时钟(RTC)是一个独立的BCD 定时器/计数器,用来提供准确的日历和时间信息。准确性是其重要的指标。
问题
某客户在其产品的设计中,使用了STM32F429IIT6。客户在使用过程发现一个问题,虽然已经有使用电池对VBAT 进行供电,
但是在经常频繁的VDD 上下电之后,发现时钟会比准确的时间慢几秒钟。
调研
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()函数,在这个函数中,可以看到以下代码:
这段代码中由于选中了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 已经被配置过的,就不需要再重新初始化一次了。如下:
结论
由于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 计时不准确,所以在实际应用过程中应该对此注意一下。
对应的代码:RTC_Calendar_CubeF4
更多实战经验请看:【ST MCU实战经验汇总贴】
|