GD32RTC备份寄存器拓展学习(掉电不丢失)

GD32RTC备份寄存器拓展学习(掉电不丢失)

刚做 RTC时钟的新手,遇到“复位/重启时间被重置”“主电源掉电后时间丢失”等问题。本文基于 GD32F470VET6+“STM32Cube HAL 直接移植到 GD32” 的实践经验,总结一套解决方案。

1. 问题现象与根因

  • **现象 A:**按复位键/软件复位后,RTC 变回默认时间(例如 12:00:00)。
  • **根因:**启动流程里每次都调用了MX_RTC_Init();,把 RTC 重新初始化。
  • **现象 B:**按复位不丢,但“主电源彻底断电”后丢。
  • **根因:**复位时 VDD 仍在,备份域不会清空;断电后若 VBAT 没真正供上(电池/接触/方向/硬件路径),备份域掉电就会丢。

2. 核心方案:备份寄存器(Backup Register)+ Magic 暗号

思路一句话:用 RTC 备份寄存器存一个“暗号(magic)”,启动时先读暗号,只有暗号不对才设置默认时间。

为什么有效:备份寄存器属于 RTC 备份域,复位一般不清空;若 VBAT 正常供电,主电源掉电也可保持。

关键点:

  • **不要求必须用“寄存器 0”。**DR0/DR1/… 任意一个都行,前提是读写一致,且不与其它用途冲突。
  • **只把 MX_RTC_Init()的SetTime/SetDate部分内容 放在“暗号不匹配”的分支里。**其它地方(主循环/按键/初始化流程)不要再重复设置时间。

3. 最小可行代码(HAL 风格,移植到 GD32 也适用)

说明:我已做过验证:写入 0x1234 后按复位,仍能读到 0x1234,证明 BKUP 读写在我的移植 HAL 上可用。

__HAL_RCC_PWR_CLK_ENABLE();//允许访问备份寄存器
HAL_PWR_EnableBkUpAccess();

/* ===== 关键:用备份寄存器判断是否“第一次初始化RTC” ===== */
if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != RTC_INIT_MAGIC)//匹配暗号,检测是否第一次上电
{

sTime.Hours = 23;
sTime.Minutes = 59;
sTime.Seconds = 30;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;

if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
{
Error_Handler();
}

sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_FEBRUARY;
sDate.Date = 18;
sDate.Year = 26;

if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
{
Error_Handler();
}

/* 若是第一次上电写入暗号:下次复位就不会再进来 */
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, RTC_INIT_MAGIC);
}

4. 必做验证(无仪器也能定位问题)

验证 1:确认“复位不丢”

  • **上电写入 0x1234 → 立刻读回 → 按复位 → 重启后再读。**如果仍是 0x1234,说明备份寄存器在复位场景可用。

验证 2:确认“断主电不丢(电池在)”

  • **装好电池 → 写入 magic → 断开主电源(USB/VDD)-> 等 3-5 分钟 → 再上电读 magic。**magic 仍在,说明 VBAT 供电链路有效。

5. 我踩过的坑与注意事项(重点!)

  • **坑 1:电池装反。**表现为:复位不丢(VDD 还在),但断主电必丢(VBAT 实际没供上)。我就是这个原因白查了很久。
  • **坑 2:以为“断电了”,其实电容在撑电。**断主电后多等一会再测(建议 1-2 分钟)。
  • **坑 3:代码里还有其他地方在 SetTime/SetDate。**全工程搜索 HAL_RTC_SetTime/HAL_RTC_SetDate 或你的 RTC_Set_xxx,确保只在“暗号不匹配”时设置。
  • **注意:读取时间/日期要遵循库要求的顺序。**常见要求是 GetTime 与 GetDate 成对调用,顺序不要乱,否则可能读到异常值。

6. 一句话总结

**复位不重置:**备份寄存器写 magic,启动先读 magic;不匹配才 SetTime/SetDate。 **掉电不丢失:**确保 VBAT 真实供电(电池方向/接触/硬件路径正确)。