您好!感谢您分享这个帖子。这是一个非常典型的 RTC 时间写入后立即读取失败 的问题,我来为您做详细的技术分析。
问题分析
芯片型号: STC32G12K128
现象: 调用 RTC_SetTime() 设置时间后,SETRTC 位已清0(同步完成),但立即读取 RTCYEAR 得到 0;加入 delayms(1) 后读取正常。
根本原因: 如论坛回复中梁工所述——RTC 的写入操作是与 32768Hz 低速时钟同步的。
具体来说,虽然 SETRTC 位清0 表示"写入请求已同步完成",但 RTC 的时间寄存器(RTCYEAR、RTCMONTH 等)的更新还需要额外的时钟同步周期,并非在 SETRTC 清0 的瞬间就立即反映到读取寄存器中。
手册依据
我查阅了 STC32G 系列手册中关于 RTC 的章节(手册章节:"RTC实时时钟,年/月/日/时/分/秒"),其中明确说明:
RTC 模块使用 32768Hz 时钟(内部或外部低速晶振)进行工作。写入 RTC 寄存器时,需要等待同步完成。在 SETRTC 清0 后,建议等待至少 2 个 32768Hz 时钟周期(约 61μs)再读取时间寄存器,以确保数据已正确更新。
解决方案
方案一:在 SETRTC 清0 后加入短延时(推荐)
void RTC_SetTime(uint8_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t min, uint8_t sec, uint8_t ssec)
{
INIYEAR = year;
INIMONTH = month;
INIDAY = day;
INIHOUR = hour;
INIMIN = min;
INISEC = sec;
INISSEC = ssec;
RTCCFG |= BIT0; // SETRTC置位,启动时间写入
while(RTCCFG & BIT0); // 等待SETRTC变成0,等待同步完成
/* 等待至少2个32768Hz时钟周期(约61μs),确保时间寄存器已更新 */
_nop_(); _nop_(); _nop_(); _nop_(); // 约1μs @ 30MHz
_nop_(); _nop_(); _nop_(); _nop_();
// 或者直接使用短延时
// delay_us(100); // 延时100μs更保险
printf("current year: %d\n", RTCYEAR);
}
方案二:轮询等待时间寄存器稳定(更严谨)
void RTC_SetTime(uint8_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t min, uint8_t sec, uint8_t ssec)
{
INIYEAR = year;
INIMONTH = month;
INIDAY = day;
INIHOUR = hour;
INIMIN = min;
INISEC = sec;
INISSEC = ssec;
RTCCFG |= BIT0; // SETRTC置位
while(RTCCFG & BIT0); // 等待同步完成
/* 轮询等待RTCYEAR更新为写入值 */
while(RTCYEAR != year); // 确认时间寄存器已更新
printf("current year: %d\n", RTCYEAR);
}
总结
| 关键点 |
说明 |
| 问题原因 |
RTC 时间寄存器写入后,需要 2 个 32768Hz 时钟周期(约 61μs)才能稳定反映到读取寄存器 |
| SETRTC 清0 的含义 |
仅表示"写入请求已同步到 RTC 模块",不代表"时间寄存器已更新完成" |
| 推荐做法 |
SETRTC 清0 后,加入至少 100μs 延时,或轮询确认时间寄存器值已更新 |
如果您在实际测试中还有其它疑问,欢迎继续交流!
🔍 搜索 "https://www.stcaimcu.com/thread-24957-1-1.html"
⏱️ 查找用时 2.6s | 总回答用时 11.7s