STM32 RTC时钟掉电日期不更新 STM32 HAL库RTC时钟配置

article/2025/8/6 21:04:58

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

STM32 RTC时钟掉电日期不更新 & STM32 HAL库RTC时钟配置

  • 一、STM32CubeMX RTC配置
  • 二、RTC初始化
  • 三、RTC日期掉电不更新(F1...这里暂时只考虑F103,其他系列未测试,对比的也只考虑F4)
  • 四、解决办法
    • 4.1、上电对时
    • 4.2、将时间和日期都换算存入到CNT寄存器中(存入时间戳)
    • 4.3、设置时间时将日期同时设置,且保存到RTC备份存储区
    • 测试结果:

一、STM32CubeMX RTC配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、RTC初始化

由于自动生成的RTC程序会在初始化时将默认时间写入到RTC寄存器中,所以这里采用RTC备份存储区(掉电/重启数据不丢失)来做标志位来存储系统时间是否已经初始化过,已经初始化则不在重新写入时间,否则会将RTC时间复位。(其他系列的也可以按此操作)
程序代码加在 /* USER CODE BEGIN Check_RTC_BKUP */区域内,否则更新STM32CubeMx文件会将修改的代码删掉。

  1. 首先判断标志位 0x55AA,标志位自己定义数值,0x55AA没有特别含义;
  2. 如果是首次烧录运行,判断你是不,往下走写入默认时间和0x55AA标志位,且将日期备份到RTC备份存储区;
  3. 第二次运行,判断成功成功,将RTC备份存储区的日期设入RTC寄存器。日期就不会恢复到0-01-01。但是还存在一个日期掉电跨天的问题,在第4步解决
/* RTC init function */
void MX_RTC_Init(void)
{/* USER CODE BEGIN RTC_Init 0 *//* USER CODE END RTC_Init 0 */RTC_TimeTypeDef sTime = {0};RTC_DateTypeDef DateToUpdate = {0};/* USER CODE BEGIN RTC_Init 1 *//* USER CODE END RTC_Init 1 *//** Initialize RTC Only*/hrtc.Instance = RTC;hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;hrtc.Init.OutPut = RTC_OUTPUTSOURCE_ALARM;if (HAL_RTC_Init(&hrtc) != HAL_OK){Error_Handler();}/* USER CODE BEGIN Check_RTC_BKUP */if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1)== 0x55AA)//判断标志位	
/*check rtc is ready running! If YES, return , otherwise set the default date and time */{	#if 1DateToUpdate.Year    = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);DateToUpdate.Month   = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3);DateToUpdate.Date    = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);DateToUpdate.WeekDay = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR5);if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}#endifreturn;}/* USER CODE END Check_RTC_BKUP *//** Initialize RTC and set the Time and Date*/sTime.Hours = 16;sTime.Minutes = 45;sTime.Seconds = 0;if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}DateToUpdate.WeekDay = RTC_WEEKDAY_THURSDAY;DateToUpdate.Month = RTC_MONTH_MAY;DateToUpdate.Date = 19;DateToUpdate.Year = 22;if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}/* USER CODE BEGIN RTC_Init 2 */HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0x55AA);//写入标志位HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, (uint16_t)DateToUpdate.Year);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, (uint16_t)DateToUpdate.Month);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, (uint16_t)DateToUpdate.Date);HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, (uint16_t)DateToUpdate.WeekDay);/* USER CODE END RTC_Init 2 */}

三、RTC日期掉电不更新(F1…这里暂时只考虑F103,其他系列未测试,对比的也只考虑F4)

STM32F103的寄存器和F4的不一样:
F4的RTC能够掉电自动更新日期,因为有TR寄存器更新时间,DR寄存器更新日期;
而F1的只能自动更新CNTH和CNTL寄存器。通过寄存器去换算成时间。但是HAL库使用寄存器的值会在跨天的时候自动清零。
F4
在这里插入图片描述
F1
在这里插入图片描述
跨天自减
在这里插入图片描述

四、解决办法

4.1、上电对时

如果对时间有非常明确的要求,有条件的采用上电对时,就不会有时间错乱。方法不多赘述。

4.2、将时间和日期都换算存入到CNT寄存器中(存入时间戳)

#include "time.h"
uint32_t stm32_rtc_timestamp(RTC_TimeTypeDef TimeStruct, RTC_DateTypeDef DateStruct)
{struct tm tm_new;tm_new.tm_sec  = TimeStruct.Seconds;tm_new.tm_min  = TimeStruct.Minutes;	tm_new.tm_hour = TimeStruct.Hours;tm_new.tm_mday = DateStruct.Date;tm_new.tm_mon  = DateStruct.Month;	tm_new.tm_year = DateStruct.Year;return mktime(&tm_new);
}

(暂时没空实现,网上有一些类似方法)但是相对来说要处理的东西比较多,参考下面这个链接其实可以用时间戳转换函数去写入和转换时间。
STM32 RTC时钟掉电日期不更新

4.3、设置时间时将日期同时设置,且保存到RTC备份存储区

1) 设置的日期保存到RTC备份存储器,用作基准时间;自己实现的RTC设置日期函数。

void Bsp_RTC_SetDate(RTC_HandleTypeDef *pRtcHandle, RTC_DateTypeDef *pDateStruct)
{ HAL_RTC_SetDate(pRtcHandle, pDateStruct, FORMAT_BIN);HAL_RTCEx_BKUPWrite(pRtcHandle, RTC_BKP_DR2, (uint16_t)pDateStruct->Year);HAL_RTCEx_BKUPWrite(pRtcHandle, RTC_BKP_DR3, (uint16_t)pDateStruct->Month);HAL_RTCEx_BKUPWrite(pRtcHandle, RTC_BKP_DR4, (uint16_t)pDateStruct->Date);HAL_RTCEx_BKUPWrite(pRtcHandle, RTC_BKP_DR5, (uint16_t)pDateStruct->WeekDay);
}void Bsp_RTC_SetTime(RTC_HandleTypeDef *pRtcHandle, RTC_TimeTypeDef *pTimeStruct)
{ HAL_RTC_SetTime(pRtcHandle, pTimeStruct, FORMAT_BIN);
}

2) 时间设置和日期设置必须保持同步;这一步是为了将基准时间(RTC备份区的日期)和偏移时间(CNTH和CNTL的自增寄存器数值)统一。stm32f1xx_hal_rtc.c文件

void Drv_RTC_CalendarSet(BSP_DateTypeDef Date, BSP_TimeTypeDef Time)
{ static RTC_DateTypeDef DateStruct;static RTC_TimeTypeDef TimeStruct;DateStruct.Year = Date.Year;DateStruct.Month = Date.Month;DateStruct.Date = Date.Date;DateStruct.WeekDay = Date.WeekDay;Bsp_RTC_SetDate(&RtcHandle,&DateStruct);TimeStruct.Hours = Time.Hours;TimeStruct.Minutes = Time.Minutes;TimeStruct.Seconds = Time.Seconds;Bsp_RTC_SetTime(&RtcHandle,&TimeStruct);
}

3) CNTL和CNTH寄存器跨天不更新;即,偏移时间counter_time必须一直自增。stm32f1xx_hal_rtc.c文件
HAL_RTC_GetTime
在这里插入图片描述

HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
{/***省略*//* Read the time counter*/counter_time = RTC_ReadTimeCounter(hrtc);/* Fill the structure fields with the read parameters */hours = counter_time / 3600U;sTime->Minutes  = (uint8_t)((counter_time % 3600U) / 60U);sTime->Seconds  = (uint8_t)((counter_time % 3600U) % 60U);if (hours >= 24U){/* Get number of days elapsed from last calculation */days_elapsed = (hours / 24U);/* Set Hours in RTC_TimeTypeDef structure*/sTime->Hours = (hours % 24U);/* Read Alarm counter in RTC registers */counter_alarm = RTC_ReadAlarmCounter(hrtc);/* Calculate remaining time to reach alarm (only if set and not yet expired)*/if ((counter_alarm != RTC_ALARM_RESETVALUE) && (counter_alarm > counter_time)){counter_alarm -= counter_time;}else{/* In case of counter_alarm < counter_time *//* Alarm expiration already occurred but alarm not deactivated */counter_alarm = RTC_ALARM_RESETVALUE;}/* Set updated time in decreasing counter by number of days elapsed *///   counter_time -= (days_elapsed * 24U * 3600U);    //modify by LeoX/* Write time counter in RTC registers */if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK){return HAL_ERROR;}  /***省略*/
}

HAL_RTC_SetDate
在这里插入图片描述

HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
{/***省略*//* Reset time to be aligned on the same day *//* Read the time counter*/counter_time = RTC_ReadTimeCounter(hrtc);/* Fill the structure fields with the read parameters */hours = counter_time / 3600U;if (hours > 24U){/* Set updated time in decreasing counter by number of days elapsed */
//    counter_time -= ((hours / 24U) * 24U * 3600U);/* Write time counter in RTC registers */if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK){/* Set RTC state */hrtc->State = HAL_RTC_STATE_ERROR;/* Process Unlocked */__HAL_UNLOCK(hrtc);return HAL_ERROR;}/***省略*/
}

4) 日期更新的时候读取RTC备份区的日期来计算偏移;在for循环中计算年月日的偏移。

static void RTC_DateUpdate(RTC_HandleTypeDef *hrtc, uint32_t DayElapsed)
{uint32_t year = 0U, month = 0U, day = 0U;uint32_t loop = 0U;
#if 0            //modify by LeoX/* Get the current year*/year = hrtc->DateToUpdate.Year;/* Get the current month and day */month = hrtc->DateToUpdate.Month;day = hrtc->DateToUpdate.Date;
#else            //modify by LeoXyear   = HAL_RTCEx_BKUPRead(hrtc, RTC_BKP_DR2);month  = HAL_RTCEx_BKUPRead(hrtc, RTC_BKP_DR3);day   = HAL_RTCEx_BKUPRead(hrtc, RTC_BKP_DR4);
#endiffor (loop = 0U; loop < DayElapsed; loop++)

测试结果:

  1. 程序下载,初始化默认的时间
    在这里插入图片描述
  2. 修改时间
    在这里插入图片描述
  3. 带电时间跨天,日期更新
    在这里插入图片描述
  4. 下电时间跨天
    在这里插入图片描述
    5) 设置时间后立即反复掉电重启
    在这里插入图片描述
    在这里插入图片描述
    说明:
    1) 以上的时间全部为测试时间,初始化默认时间和STM32CubeMx的对应不上是因为以及做过几轮测试;
    2) 这个方法要改到库函数,修改库函数后要备份保存好,否则一旦重新获取HAL库,修改都会被覆盖掉。
    3) 仅作参考。4.2的方法有空再实现。
    4) 相对来说4.1的改动最小,不用自己去写日期判断函数,去处理时间戳转换。
    5) 只有在上电和更新时间的时候会写RTC备份存储区。获取时间的时候只读,所以反复读取对寿命无影响。
    6) 参考程序:STM32CubeMX RTC配置 STM32 RTC时钟掉电日期不更新

http://chatgpt.dhexx.cn/article/fa1xAMhV.shtml

相关文章

STM32CubeMX | 基于STM32使用HAL库驱动RTC时钟及闹钟功能

STM32CubeMX | 基于STM32使用HAL库驱动RTC时钟及闹钟功能 目录 STM32CubeMX | 基于STM32使用HAL库驱动RTC时钟及闹钟功能&#xff08;一&#xff09;工程配置&#xff08;二&#xff09;代码编写&#xff08;三&#xff09;运行效果 本章实现效果&#xff1a; RTC时钟获取周期…

STM32G4之RTC实时时钟

文章目录 前言一、RTC介绍二、STM32CubeMX配置三、部分源码总结 前言 一、RTC介绍 STM32 的 RTC 外设&#xff08;Real Time Clock&#xff09; &#xff0c;实质是一个掉电后还继续运行的定时器。STM32G4 的 RTC&#xff0c;是一个独立的 BCD 定时器/计数器。 RTC 提供一个日历…

什么是RCT实时时钟?(STM32中RTC时钟源)

什么是RCT&#xff08;Real Time Clock&#xff0c;实时时钟&#xff09;? 一、RTC时钟简介 RTC&#xff08;Real Time Clock&#xff0c;实时时钟&#xff09;是指安装在电子设备或实现其功能的IC&#xff08;集成电路&#xff09;上的时钟&#xff0c;一般会是集成电路&am…

STM32:RTC实时时钟原理

RTC (Real Time Clock)&#xff1a;实时时钟 RTC是个独立的BCD定时器/计数器。RTC 提供一个日历时钟&#xff0c;两个可编程闹钟中断&#xff0c;以及一个具有中断功能的周期性可编程唤醒标志。RTC还包含用于管理低功耗模式的自动唤醒单元。 两个32位寄存器包含二进码十进制格式…

STM32物联网项目-RTC时钟

RTC时钟 RTC简介 实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器&#xff0c;在相应软件配置下&#xff0c;可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。 RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域&#xff0c;即在系…

十九、RTC实时时钟

一、.RTC实时时钟工作框图 RTC 由两个主要部分组成&#xff0c;第一部分(APB1 接口)用来和 APB1 总线相连。此单元还包含一组 16 位寄存器&#xff0c;可通过 APB1 总线对其进行读写操作。APB1 接口由 APB1 总线时钟驱动&#xff0c;用来与 APB1 总线连接。 RTC_PRL设置100&a…

STM32 RTC时钟读取时间

文章目录 一、RTC简介1.1 RTC1.2 RTC特征1.3 RTC原理框图1.4 RTC工作流程1.5 RTC时钟选择1.6 RTC复位过程1.7 RTC中断 二、CubeMX配置2.1 RCC配置2.2 SYS配置2.3 RTC配置2.4 串口配置2.5 时钟配置2.6 生成项目代码 三、代码编写3.1 重写printf3.2 RTC_HAL库函数/*设置系统时间*…

STM32 RTC实时时钟

我用的是STM32库函数&#xff1a;两个知识点&#xff1a; 一、RTC时钟框图分析&#xff08;重要&#xff09; 二、时间是怎样显示出来的&#xff08;简析&#xff09; 一、RTC时钟框图分析&#xff08;重要&#xff09; 先熟悉一下几个知识点&#xff1a; …

STM32之RTC时钟,闹钟,日历

RTC时钟的一些功能介绍 RTC时钟即实时时钟&#xff0c;它提供了用于管理所有低功耗模式的自动唤醒单元&#xff0c;还提供了具有可编程闹钟中断功能的日历时钟/日历。 并且可以自动将月份的天数补偿为 28、29&#xff08;闰年&#xff09;、30 和 31 天。并且还可以进行夏令时…

深入学习RTC时钟库 DS1302

❤️博主介绍❤️ &#x1f62c; 作者&#xff1a;单片机菜鸟哥 &#x1f449;火爆博客&#xff1a;ESP8266 Arduino教程 零基础从入门到熟悉Arduino平台下开发ESP8266&#xff0c;同时会涉及网络编程知识。专栏文章累计超过60篇&#xff0c;分为基础篇、网络篇、应用篇、高级篇…

深入学习 RTC时钟库 DS3231

❤️博主介绍❤️ &#x1f62c; 作者&#xff1a;单片机菜鸟哥 &#x1f449;火爆博客&#xff1a;ESP8266 Arduino教程 零基础从入门到熟悉Arduino平台下开发ESP8266&#xff0c;同时会涉及网络编程知识。专栏文章累计超过60篇&#xff0c;分为基础篇、网络篇、应用篇、高级篇…

rtc时钟

一、设计效果 配置RTC时钟&#xff0c;初始化为2000年1月1日00:00:00&#xff1b;通过RTC时钟秒中断串口每秒打印一次当前时刻&#xff0c;并切换一次流水灯状态&#xff1b;配置闹铃为10:00:05&#xff0c;在闹铃中断中每秒切换一次蜂鸣器状态闹铃&#xff0c;直到按KEY1关闭…

RTC时钟实现实时日历

文章目录 1、RTC时钟简介1.2、初识RTC1.2、相关寄存器 2、创建项目23、完善代码4、总结 1、RTC时钟简介 1.2、初识RTC 1、简介&#xff1a; RTC—real time clock&#xff0c;实时时钟&#xff0c;主要包含日历、闹钟和自动唤醒这三部分的功能&#xff0c;其中的日历功能我们使…

STM32之RTC时钟

前言 了解实时时钟RTC的原理。STM32芯片自带RTC&#xff0c;因此不须像其他MCU需外接RTC模块。请编程实现STM32的日历读取、设置和输出。要求&#xff1a; 1&#xff09;读取RTC初始时间&#xff0c;验证是否为 1970年1月1日零分零秒&#xff1b; 2&#xff09;将RTC时间调整为…

【STM32】HAL库 STM32CubeMX教程十三---RTC时钟

前言&#xff1a; 本系列教程将 对应外设原理&#xff0c;HAL库与STM32CubeMX结合在一起讲解&#xff0c;使您可以更快速的学会各个模块的使用 所用工具&#xff1a; 1、芯片&#xff1a; STM32F407ZET6/ STM32F103ZET6 2、STM32CubeMx软件 3、IDE&#xff1a; MDK-Keil软…

【STM32】详解RTC实时时钟的概念和配置示例代码

一、什么是RTC RTC(Real-time Clock)&#xff1a;实时时钟&#xff0c;本质上是一个支持BCD编码的定时器/计数器。主电源断电后能够由电池供电&#xff0c;使其时钟跳转依然正常。 二、STM32F4芯片内的RTC功能 ①日历时钟&#xff08;时分秒、年月日、星期&#xff09; ②两个闹…

android小错误:Failure retrieving text 0x7f050001 in package

1.在启动android应用程序的过程中&#xff0c;logcat打印如下的错误&#xff1a; 报错的原因&#xff1a;资源的id没有找到。资源在R.java文件中&#xff0c;找到0x7f050001 对应的定义 R.java public static final int AppTheme0x7f050001; AppTheme这个文件在AndroidMan…

Windows7系统蓝屏-解决办法, 错误代码:0x0000007F

1.电脑突然蓝屏提示stop:0x0000007F&#xff0c;如下图所示&#xff1a; 2.故障排除 重启电脑&#xff0c;一直按F8&#xff0c;进入“安全模式”&#xff0c;如能正常进入系统&#xff0c;查看系统错误日志。针对系统记录的错误日志&#xff0c;解决问题。如下图&#xff0c;…

java.lang.IllegalArgumentException No view found for id 0x7

java.lang.IllegalArgumentException No view found for id 0x7 布局上找不到这个View&#xff0c;看下ERROR的地方&#xff0c;可以看到是因为Container找不到因此报错了。 从布局入手&#xff0c;参考了很多文章主要分为以下两种原因 1 Fragment 嵌套了 Fragment 例如&…

Fragment报java.lang.IllegalArgumentException:No view found for id 0x7f070250的错误

我用的是Fragment嵌套Fragment做的&#xff0c;放fragment切换快的时候程序就会崩溃&#xff0c;解决这个办法就是在View生成前先将FragemnentManger创建好&#xff0c;就不会报错了