stm32 每次复位启动RTC时间都会变慢

困扰我一天多时间的问题,RTC时间变慢!这个你肯定会说晶振有问题,起振电容不匹配等等!额其实我也这么认为!应用场景如下:

低功耗项目需求,stm32L412CBUx芯片每次执行完动作后进入STOP模式,然后通过RTC闹钟唤醒再进行动作,这个顺序周而复始。但是每次动作记录下的数据时间却发现怪怪的,时间和手机标准时间慢了好多,运行20分钟慢了将近8分钟左右,那是多么恐怖!

于是将其每次打印出来,果不出所料!怎么会变慢的呢?32.768K晶振这个物料和上次不一样还是电容使用了12pF ? 恩换一下吧,两个都换了没发现什么改变的,再用示波器观察下波形,波形频率也挺好的。每次唤醒电源有问题?用示波器观察了下3.3V的纹波,20mv下,挺好的。晕了!那软件问题?屏蔽下各部分?屏蔽下无关部分?再用cubemx新建工程?都没用!!!看了所以网上的rtc时钟变慢的文章都没什么发现!晚上8点了,哎回去吧!在路上地铁上拿着手机继续搜索这这个问题。第二天过来想了想,理清下思路,要是不断复位会不会影响这个时钟呢。一边看着电脑秒钟输出和串口打印的时间,同时不停按复位键,不用几下时间明显变慢了。哦原来真的是复位引起,于是后来改变搜索问题的关键词,让我有点启发的文章:

https://blog.csdn.net/liaronbob/article/details/86091574

真的感谢这篇博文,让我开始怀疑RTC初始化函数,其实我有个疑问的,因为程序我是要操作RTC的,这里不初始化能执行其指针下的成员吗?按照文章操作结果读出来备份寄存器为0. 有点将信将疑,读取时间没问题,但就是备份寄存器读不出来也没复位的。答案浮出来了。果然是上边文章的原因。如下:

http://www.51hei.com/bbs/dpj-76620-1.html

那么这个初始化函数肯定有初始化什么标志位才可以正常读取备份寄存器的。经过细看这个初始化函数以及手册。恩发现了: TampOffset; /*!< Offset to TAMP instance */ 这个指针偏移

于是代码修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//RTC部分
void RTC_Init( )
{
    RCC_OscInitTypeDef        RCC_OscInitStruct;
        RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;
    RTC_TamperTypeDef  stamperstructure;
    /* Set Voltage scale1 as MCU will run at 32MHz */
        __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_RCC_RTC_ENABLE();

    /*这里并不是每次上电都要初始化RTC,根据第0个备份寄存器的数组决定。因为在不断复位启动执行吃时候RTC,
    RTC的时间将会变慢,大概一次复位将会慢半秒到一秒,这个真的可怕啊!我的项目应用是需要在stop模式下唤
    醒并复位,相当于不断时间变成一半,这个问题搞了我快两天的工作时间,真是HAL的坑啊!20201204*/
    RtcHandle.TampOffset = (TAMP_BASE - RTC_BASE);//一定加这句,不然在不初始化HAL_RTC_Init()的时候,执行HAL_RTCEx_BKUPRead(&RtcHandle,RTC_BKP_DR0)读取不成功且为0
    RtcHandle.Instance            = RTC;
    if(HAL_RTCEx_BKUPRead(&RtcHandle,RTC_BKP_DR0)!=0X6050)//是否第一次配置
    {
        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 */
         
        }
       
    //  if(HAL_RTCEx_BKUPRead(&RtcHandle,RTC_BKP_DR0)!=0X6050)//是否第一次配置
    //  {
        RTC_Set_Time(15,11,0,RTC_HOURFORMAT12_PM);          //设置时间 ,根据实际时间修改
            RTC_Set_Date(19,12,17,2);                           //设置日期
        HAL_RTCEx_BKUPWrite(&RtcHandle,RTC_BKP_DR0,0X6050);//标记已经初始化过了
    }
}

RTC初始化的代码,就是只要备份寄存器不复位都不再进行RTC初始化,同时可以操作RTC!

这个真的ST官方的HAL库害死人了。。。。。。。怪不得那么多人说HAL库的RTC就是BUG!!!! 我这个需要是非常常见的,特别现在那么多低功耗的项目,希望帮到有需要的朋友!

帮到你的话感谢打赏哈哈!