你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103 RTC 休眠唤醒后 读到的时间不对

[复制链接]
憨客鱼 提问时间:2026-3-11 19:39 / 未解决

我使用RTC 进行休眠唤醒,进入休眠电流值 OK, RTC 也能唤醒,但是唤醒后 RTC 读到的时间就不对了,请问是什么原因

HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);

sTime.Seconds  = sTime.Seconds  + 30;
if(sTime.Seconds>=60)
{
    sTime.Seconds = sTime.Seconds -60;
    sTime.Minutes = sTime.Minutes +1;
}
if(sTime.Minutes >=60)
{
    sTime.Minutes = sTime.Minutes  -60;
    sTime.Hours  = sTime.Hours  +1;

}

g_sAlarm.AlarmTime.Hours = sTime.Hours ; g_sAlarm.AlarmTime.Minutes = sTime.Minutes; g_sAlarm.AlarmTime.Seconds = sTime.Seconds; g_sAlarm.Alarm= RTC_ALARM_A;

// HAL_PWR_EnableBkUpAccess();

HAL_RTC_SetAlarm_IT(&hrtc, &g_sAlarm, RTC_FORMAT_BIN);

HAL_Delay(1);


HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);

__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);

HAL_PWR_EnableBkUpAccess();                 

// HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
HAL_PWR_EnterSTANDBYMode();

SystemClock_Config();

// SystemClock_RestoreFromStop(); MX_GPIO_Init(); MX_TIM6_Init(); MX_ADC1_Init(); // MX_RTC_Init(); // My_RTC_Init(); MX_SPI2_Init(); MX_UART4_Init(); HAL_Delay(10); Fun_Main_Init();

收藏 评论16 发布时间:2026-3-11 19:39

举报

16个回答
憨客鱼 回答时间:2026-3-17 09:26:45

xmshao 发表于 2026-3-14 09:46
保证VDD和VBAT至少有一个存在的情况下,复位芯片或低功耗唤醒是不会影响RTC工作的。</p>
<p>你先保证正常模 ...

[md]我直接在休眠前读 时间 和休眠后马上读时间,还是不对

这个是休眠前的代码

HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);     

printf("\n year = %d",sDate.Year);
printf(" month = %d",sDate.Month);
printf(" data = %d",sDate.Date);    
printf("\n hour = %d",sTime.Hours);         
printf(" min = %d",sTime.Minutes);                  
printf(" sec = %d",sTime.Seconds);                  


sTime.Seconds  = sTime.Seconds  + 30;
if(sTime.Seconds>=60)
{
    sTime.Seconds = sTime.Seconds -60;
    sTime.Minutes = sTime.Minutes +1;
}
if(sTime.Minutes >=60)
{
    sTime.Minutes = sTime.Minutes  -60;
    sTime.Hours  = sTime.Hours  +1;

}

g_sAlarm.AlarmTime.Hours = sTime.Hours ; g_sAlarm.AlarmTime.Minutes = sTime.Minutes; g_sAlarm.AlarmTime.Seconds = sTime.Seconds; g_sAlarm.Alarm= RTC_ALARM_A;

// HAL_PWR_EnableBkUpAccess();

HAL_RTC_SetAlarm_IT(&hrtc, &g_sAlarm, RTC_FORMAT_BIN);

HAL_Delay(1);


HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);

__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);

HAL_PWR_EnableBkUpAccess();                 

// HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); HAL_PWR_EnterSTANDBYMode();

这个是系统开机的代码

HAL_Init();

/ USER CODE BEGIN Init /

/ USER CODE END Init /

/ Configure the system clock / SystemClock_Config();

/ USER CODE BEGIN SysInit /

/ USER CODE END SysInit /

/ Initialize all configured peripherals / MX_GPIO_Init(); if(HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR1)!=0X32F2) {

HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0x32F2);
// RTC_CalendarConfig(); MX_RTC_Init();
} else { /
hrtc.Instance->CRL &=~0x08; while((hrtc.Instance->CRL&0x08)==0x08); hrtc.Instance->CRL |=0x08;
/

HAL_RTC_GetTime(&hrtc, &g_sTimeTemp, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &g_sDateTemp, RTC_FORMAT_BIN);   

} // MX_RTC_Init(); MX_UART4_Init(); MX_TIM6_Init(); MX_SPI2_Init(); MX_ADC1_Init(); / USER CODE BEGIN 2 /

printf("\n idle year = %d",g_sDateTemp.Year); printf(" idle month = %d",g_sDateTemp.Month); printf(" idle data = %d",g_sDateTemp.Date);

printf("\n hour = %d",g_sTimeTemp.Hours);
printf(" min = %d",g_sTimeTemp.Minutes);
printf(" sec = %d",g_sTimeTemp.Seconds); 这个是打印出来的结果

image.png

憨客鱼 回答时间:2026-3-13 10:56:27

butterflyspring 发表于 2026-3-12 10:02
看到代码中进入了 STANDBY 模式。 这个模式唤醒后代码会从头新执行,类似与复位。</p>
<p>After waking up from S ...

我把MX_RTC_Init 函数下面这段代码// 掉了,但是还是不对,是不是可以认为,只要RTC 初始化过了,时间就不对了,那我该怎么处理呢,我尝试用一个寄存器做标注,但是重启后这个寄存器好像也呗初始化了

/ USER CODE BEGIN Check_RTC_BKUP /

/ USER CODE END Check_RTC_BKUP /

/* Initialize RTC and set the Time and Date / /* sTime.Hours = 0; sTime.Minutes = 0; sTime.Seconds = 0;

if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY; DateToUpdate.Month = RTC_MONTH_JANUARY; DateToUpdate.Date = 1; DateToUpdate.Year = 0;

if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } */

憨客鱼 回答时间:2026-3-13 18:46:15

xmshao 发表于 2026-3-13 12:03
我找了下,有的。 不同系列寄存器有点不一样,F1系列在RTC_CRL。</p>
<p>![image.png](data/attachment/forum/ ...

[md]if(HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR1)!=0X32F2) { HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0x32F2); // RTC_CalendarConfig(); MX_RTC_Init(); } else { hrtc.Instance->CRL &=~0x08; while((hrtc.Instance->CRL&0x08)==0x08); hrtc.Instance->CRL |=0x08; }

改成这样 还是不对

摩洛哥的制砖匠人 回答时间:2026-3-12 08:35:07

外部电池,外部晶振

butterflyspring 回答时间:2026-3-12 10:02:41
看到代码中进入了 STANDBY 模式。 这个模式唤醒后代码会从头新执行,类似与复位。

After waking up from Standby mode, program execution restarts in the same way as after a
Reset (boot pins sampling, vector reset is fetched, etc.).

所以检查一下代码开始,是不是没有判断RTC被初始化过还是上电复位,从而决定是否需要重新初始化RTC。
如果没有这一步,那么每次唤醒都会初始化RTC从而使得时间不能连续。 库中有例程可以参考。

STM32F103 RTC standby wakeup.PNG

xmshao 回答时间:2026-3-12 17:10:55
  1. 你唤醒后或者复位后,你这样操作:

    清 RSF → 等 RSF 置 1 → 再读时间,再读日期。

  2. 读操作不要只读一部分,时分秒日期都要读取,先读时间 后读日期。

憨客鱼 回答时间:2026-3-13 11:18:55

xmshao 发表于 2026-3-12 17:10</p>
<ol>
<li>
<p>你唤醒后或者复位后,你这样操作:</p>
<p>清 RSF → 等 RSF 置 1 → 再读时间,再读日期。

[md]好像没找到这个寄存器

c7a6c801-d150-44d9-9eb9-af9cd49b2fe2.png

9727db05-2b7d-47a1-8a77-c3c1bac330ac.png
9727db05-2b7d-47a1-8a77-c3c1bac330ac.png
9727db05-2b7d-47a1-8a77-c3c1bac330ac.png
xmshao 回答时间:2026-3-13 12:03:30

我找了下,有的。 不同系列寄存器有点不一样,F1系列在RTC_CRL。

image.png

关键地方,就是你每次读日历时,保证按照先读TIME,再读DATE的步骤进行很重要。

butterflyspring 回答时间:2026-3-13 15:05:32
可以参考库中的例程,用备份域寄存器作为标志来判断是否掉过电。
\STM32Cube_FW_F1_V1.8.6\Projects\STM3210E_EVAL\Examples\RTC\RTC_Calendar




STM32F103 RTC DEMO CODE .PNG

xmshao 回答时间:2026-3-13 17:25:37

憨客鱼 发表于 2026-3-13 10:56
我把MX_RTC_Init 函数下面这段代码// 掉了,但是还是不对,是不是可以认为,只要RTC 初始化过了,时 ...

[md]怎么来回初始化呢。

你初始化后,建个标志. STM32F1系列里常用个备份域寄存器来做标志。

每次复位后检查该标志,如果该标志已经被你设置过了,就跳过RTC的初始化。

憨客鱼 回答时间:2026-3-13 18:01:30

butterflyspring 发表于 2026-3-13 15:05
可以参考库中的例程,用备份域寄存器作为标志来判断是否掉过电。
\STM32Cube_FW_F1_V1.8.6\Projects\STM321 ...

RTC_CalendarConfig 找不到这个函数啊

憨客鱼 回答时间:2026-3-13 18:41:26

xmshao 发表于 2026-3-13 17:25
怎么来回初始化呢。</p>
<p>你初始化后,建个标志. STM32F1系列里常用个备份域寄存器来做标志。

[md]不好意思,刚才搞晕了,这个方法的却是可以知道是不是休眠重启,但是这样休眠重启后RTC数据还是不对啊

xmshao 回答时间:2026-3-14 09:46:42

憨客鱼 发表于 2026-3-13 18:41
不好意思,刚才搞晕了,这个方法的却是可以知道是不是休眠重启,但是这样休眠重启后RTC数据还是不对 ...

[md]保证VDD和VBAT至少有一个存在的情况下,复位芯片或低功耗唤醒是不会影响RTC工作的。

你先保证正常模式下 RTC正在工作,读取正常。确保LSE工作稳定、代码正常。

然后再验证低功耗,或重启,重启的话必须保证VDD和VBAT至少一个有电~!

butterflyspring 回答时间:2026-3-17 16:49:54
从打印结果上看,SEC 在增加,RTC 在低功耗下并没有停,是吧 ?


12下一页
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版