anikiVV 2024-03-04 11:49 采纳率: 0%
浏览 161

STM32的RTC不准

使用STM32标准库编写的RTC时钟用了一两天后不准的问题,误差会有几十秒,有时快有时慢,使用了外部晶振32.768和3V纽扣电池供电VBAT。
当我使用MyRTC_SetTime设置时间的时钟,使用一两天后,RTC时钟就会出现偏差。使用的备用电池。
代码是参考江科大的:


void MyRTC_Init(void)
{
//第一步:配置BKP备份寄存器,由备用电源供应
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); //开启PWR的时钟,挂载在APB1上
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE); //开启BKP的时钟,挂载在APB1上

PWR_BackupAccessCmd(ENABLE);      //备份访问控制

if(BKP_ReadBackupRegister(BKP_DR1) !=0xA5A5)  //如果BKP没被清零就代表没断电。因为每次初始化RTC都会被清零。所以加个判断断电初始化
{
    
        //第二步:开启LSE时钟,32.768khz的,并等待LSE时钟启动完成

        RCC_LSEConfig(RCC_LSE_ON);       //如果LSE晶振不起振,就会卡死
        /*备用方法:使用LSI内部晶振
        RCC_LSICmd(ENABLE);
        while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)!=SET); //等待标志位完成
        
        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //RCC时钟选择LSI
        */
        
        //RCC_GetFlagStatus(RCC_FLAG_LSERDY);  //获取LES时钟准备标志位
        while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)!=SET); //等待标志位完成
        
        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //RCC时钟选择LSE
        RCC_RTCCLKCmd(ENABLE);  
        
        RTC_WaitForSynchro();  //等待同步函数
        RTC_WaitForLastTask(); //等待上一次操作完成
        
        //第三步:配置PSC预分频器得到1HZ频率
         
        RTC_SetPrescaler(32768-1);   //当使用LSE的时候预分配32768-1得到1HZ,当使用LSI的时候预分配40000-1得到1HZ
        RTC_WaitForLastTask(); //等待上一次操作完成

        //设置时间
        //MyRTC_SetTime(1672588795);

        BKP_WriteBackupRegister(BKP_DR1,0xA5A5);  //把BKP写上

}
else
{
    RTC_WaitForSynchro();  //等待同步函数
    RTC_WaitForLastTask(); //等待上一次操作完成

}

}
//设置起始时间戳
void MyRTC_SetTime(u32 time_cnt)
{

RTC_SetCounter(time_cnt);
RTC_WaitForSynchro();  //等待同步函数
RTC_WaitForLastTask(); //等待上一次操作完成
}

//读当前时间
u32 MyRTC_ReadTime(void)
{
return RTC_GetCounter();//读取CNT的秒数。8小时偏移
}
  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-03-04 11:50
    关注

    引自免费微信小程序:皆我百晓生

    针对STM32 RTC 准确性问题,可能的原因和解决方法如下:

    1. 外部晶振稳定性问题:首先,请确认你的32.768kHz外部晶振(LSE)是否足够稳定。晶振本身的精度、负载电容匹配以及PCB走线布局都可能影响其长期稳定性。若怀疑晶振有问题,可以尝试更换高质量的晶振,并确保电路设计合理。

    2. RTC 配置检查

      • 在代码中,你已经正确配置了使用外部LSE作为RTC时钟源,同时设置了预分频器以得到1Hz的频率。
      • 确保在设置时间前,等待RTC同步和上一次任务完成,这部分代码看起来是正确的。
    3. 电源噪声干扰:RTC由VBAT供电,应确保VBAT电源干净无噪声,避免电源波动对RTC计时造成影响。可以在VBAT和地之间增加滤波电容以提高电源质量。

    4. 温度漂移:晶振受温度影响会有一定频率漂移,这可能导致长时间运行后产生累计误差。对于工业级或更高级别的应用,可以选择低温度系数的晶体来减少此类误差。

    5. 软件处理:虽然你提供的初始化和设置时间的代码看起来基本正确,但没有提供RTC中断重置累加误差的机制。为了保证长期准确,可以定期校准RTC,例如每天通过网络获取精确时间进行校准,或者利用RTC的秒中断定时做软件补偿。

    6. 硬件故障排除:检查STM32 RTC模块和外部晶振连接的线路是否有短路、断路等问题,也需排查电池电压是否正常。

    基于以上分析,如果你的问题依然存在,建议按照以下步骤进一步排查:

    • 使用示波器检查LSE晶振输出信号的稳定性。
    • 增加RTC中断并编写相应处理函数,实现周期性的时间校准。
    • 考虑采用RTC的Tamper功能或Wake-up功能结合纽扣电池掉电检测,以便在系统上电时自动校正RTC时间。

    由于无法直接在线调试和测试,这里不能给出针对性的代码修改,但可以提供一个参考思路,例如添加校准逻辑的大致框架:

    // 添加到主循环或定时器中断中,每天校准一次RTC时间
    void Daily_RTC_Calibration(void) {
        u32 network_time; // 获取网络或其他精确时间源的时间戳
        u32 rtc_time = MyRTC_ReadTime(); // 读取RTC当前时间
    
        // 计算差值并调整RTC时间
        u32 time_difference = network_time - rtc_time;
        if (time_difference > MAX_ACCEPTABLE_ERROR) {
            MyRTC_SetTime(network_time);
        }
    }
    

    请根据实际情况调整上述代码以适应你的系统架构。

    评论

报告相同问题?

问题事件

  • 创建了问题 3月4日