GD32F103C8T6 RTC 待机模式唤醒后能够记录时间但是不走时
MUC是GD32F103C8T6,初次上电配置RTC并写入初始时间。时钟源选择了内部40k(暂时没有接外部低速时钟)想要实现的是在低功耗情况下的日历更新。即在待机模式下进行RTC走时。
待机模式唤醒以后,没有再次配置RTC的情况下APB与寄存器同步一直等待。待机模式唤醒后,如果重新配置RTC配置项除了不复位备份域其他与初次上电的配置完全相同,此时可以同步APB和寄存器,但是读出的数值是进入待机模式时最后保存的时间。
现在的问题是,为什么不配置RTC的情况下无法同步APB和寄存器,为啥同步了二者之后似乎在待机的状态下RTC并没有走时。
请各位大能指点一二。
不知道你这个问题是否已经解决, 如果还没有解决的话:根据问题描述,主要有两个问题需要解决: 1. 在不重新配置RTC的情况下无法同步APB和寄存器的问题。 2. 重新配置RTC后,在待机状态下RTC仍然没有走时的问题。
首先,我们来解决第一个问题。从参考资料中可以看到,当后备电源断电之后,RTC相关寄存器和后备寄存器的值会丢失。因此,在待机模式唤醒后,APB和寄存器无法同步。为了解决这个问题,我们需要在待机模式唤醒后,重新配置RTC的值。
解决方法是,在RTC配置时,将当前时间写入RTC计数器中,并在后备寄存器中写入一个特殊字符作为标志检查位,以便下次进行检查。具体步骤如下:
下面是按照上述步骤编写的代码示例:
#include "gd32f10x.h"
// 初始化RTC
void RTC_Init() {
// 启用Power Clock时钟
RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_PWR, ENABLE);
// 解锁电源管理单元
PWR_BackupAccess_Enable(ENABLE);
// 启用RTC时钟
RCC_LSI_Enable(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
RCC_RTCCLK_Enable(ENABLE);
// 配置RTC
RTC_DeInit();
RTC_SetPrescaler(32767); // RTC 1秒钟计数器周期为1Hz
RTC_WaitSync();
RTC_WaitForLastTask();
}
// 获取当前时间
void RTC_GetTime(uint32_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second) {
while (RTC_GetFlagStatus(RTC_FLAG_RTOFF) == RESET);
RTC_WaitForLastTask();
*year = RTC_GetCounter() / 31536000 + 1970;
uint32_t days = RTC_GetCounter() % 31536000 / 86400;
*month = 1;
while (days > 0) {
uint8_t month_days = 30;
if (*month == 2) {
month_days = ((RTC_GetCounter() / 31536000 + 1970) % 4 == 0) ? 29 : 28;
} else if (*month == 1 || *month == 3 || *month == 5 || *month == 7 || *month == 8 || *month == 10 || *month == 12) {
month_days = 31;
}
if (days >= month_days) {
days -= month_days;
(*month)++;
} else {
break;
}
}
*day = days + 1;
*hour = (RTC_GetCounter() % 86400) / 3600;
*minute = (RTC_GetCounter() % 3600) / 60;
*second = (RTC_GetCounter() % 3600) % 60;
}
// 设置当前时间
void RTC_SetTime(uint32_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
while (RTC_GetFlagStatus(RTC_FLAG_RTOFF) == RESET);
RTC_WaitForLastTask();
uint32_t total_seconds = 0;
for (uint32_t i = 1970; i < year; i++) {
if ((i % 4 == 0 && i % 100 != 0) || i % 400 == 0) {
total_seconds += 31622400; // 闰年的秒钟数
} else {
total_seconds += 31536000; // 平年的秒钟数
}
}
for (uint8_t i = 1; i < month; i++) {
uint8_t month_days = 30;
if (i == 2) {
month_days = ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ? 29 : 28;
} else if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12) {
month_days = 31;
}
total_seconds += month_days * 86400; // 月份秒钟数相加
}
total_seconds += (day - 1) * 86400;
total_seconds += hour * 3600;
total_seconds += minute * 60;
total_seconds += second;
RTC_SetCounter(total_seconds);
RTC_WaitForLastTask();
}
// 待机模式唤醒时重新同步APB和寄存器
void RTC_SyncClock() {
RCC_ResetFlag();
RCC_PCLK1Config(RCC_HCLK_Div8);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_ClocksTypeDef RCC_Clocks;
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);
}
int main() {
RTC_Init();
if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) {
// 第一次上电配置RTC,设置初始时间
RTC_SetTime(2022, 10, 1, 12, 0, 0);
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); // 设置标志位
}
// 进入待机模式
PWR_EnterSTANDBYMode();
// 唤醒后重新同步APB和寄存器
RTC_SyncClock();
// 读取当前时间
uint32_t year;
uint8_t month, day, hour, minute, second;
RTC_GetTime(&year, &month, &day, &hour, &minute, &second);
// 输出当前时间
printf("Current Time: %04d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second);
return 0;
}
接下来,我们来解决第二个问题:重新配置RTC后,在待机状态下RTC仍然没有走时的问题。
根据参考资料,RTC 的走时依赖于 RTC 时钟源。在 GD32F103C8T6 上配置 RTC 的时钟源为内部 40k 时钟源。根据 GD32F10x 参考手册的描述,待机模式下 RTC 的时钟源可以选择内部 40k 时钟源或外部低速时钟。
为了使 RTC 在待机模式下继续走时,需要满足以下两个条件: 1. 配置 RTC 时钟源为外部低速时钟(如果没有接入外部低速时钟,则无法满足该条件)。 2. 在待机模式唤醒后重新初始化 RTC。
由于没有接入外部低速时钟,我们无法满足第一个条件,因此 RTC 在待机模式下无法继续走时。如果需要实现该功能,需要将外部低速时钟接入到 GD32F103C8T6,并重新配置 RTC 的时钟源。
回答问题: 针对问题标题为 "GD32F103C8T6 RTC 待机模式唤醒后能够记录时间但是不走时" 的问题,根据已有的参考资料和知识,我的解决方案如下:
以上是根据已有的参考资料和知识给出的解决方案,如果还有其他问题或需要进一步细化的部分,请提供更多的信息。