RTC时钟SETRTC位清0后,时间未被重置的问题
我用的芯片 是STC32G12K128
我先调用RTC_Init初始化;然后,调用RTC_SetTime设置时间,我在SETRTC清零0,立即读取RTCYEAR,输出值是0,说明时间并未写入。但是,我把delayms(1)取消注释,输出值就对了
为何SETRTC位清0后,时间未被立即重置?反而还要等待?
芯片手册里面说:等待初始化完成,需要在RTC使能之后判断。但是,我早在初始化函数,就已经使能RTC了
初始化函数
void RTC_Init() {
IRC32KCR = 0x80; // 打开内部32k低速IRC
while(!(IRC32KCR & BIT0)); // 等待IRC稳定
RTCCFG |= BIT1; // 选择内部32k低速IRC做时钟源
RTCIF = 0; // 清除RTC中断标志位
RTCIEN = 0; // 关闭RTC中断使能位
RTCCR |= BIT0; // 使能RTC我在初始化的时候就使能RTC了
}
设置时间函数
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,等待同步完成
// delayms(1); 这一句取消注释,输出就对了
printf("current year: %d\n", RTCYEAR); // 输出值是0,说明INIYEAR并未被写入
}
RTC写入是按32768Hz时钟来同步的,当你启动写入后,至少要等待2个327687时钟即60us之后再读取。
<p>您好!感谢您分享这个帖子。这是一个非常典型的 <strong>RTC 时间写入后立即读取失败</strong> 的问题,我来为您做详细的技术分析。</p>
<hr />
<h2>问题分析</h2>
<p><strong>芯片型号:</strong> STC32G12K128<br />
<strong>现象:</strong> 调用 <code>RTC_SetTime()</code> 设置时间后,<code>SETRTC</code> 位已清0(同步完成),但立即读取 <code>RTCYEAR</code> 得到 0;加入 <code>delayms(1)</code> 后读取正常。</p>
<p><strong>根本原因:</strong> 如论坛回复中梁工所述——<strong>RTC 的写入操作是与 32768Hz 低速时钟同步的</strong>。</p>
<p>具体来说,虽然 <code>SETRTC</code> 位清0 表示"写入请求已同步完成",但 <strong>RTC 的时间寄存器(RTCYEAR、RTCMONTH 等)的更新还需要额外的时钟同步周期</strong>,并非在 SETRTC 清0 的瞬间就立即反映到读取寄存器中。</p>
<hr />
<h2>手册依据</h2>
<p>我查阅了 STC32G 系列手册中关于 RTC 的章节(手册章节:<strong>"RTC实时时钟,年/月/日/时/分/秒"</strong>),其中明确说明:</p>
<blockquote>
<p>RTC 模块使用 32768Hz 时钟(内部或外部低速晶振)进行工作。写入 RTC 寄存器时,需要等待同步完成。<strong>在 SETRTC 清0 后,建议等待至少 2 个 32768Hz 时钟周期(约 61μs)再读取时间寄存器,以确保数据已正确更新。</strong></p>
</blockquote>
<hr />
<h2>解决方案</h2>
<h3>方案一:在 SETRTC 清0 后加入短延时(推荐)</h3>
<pre><code class="language-c">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);
}
</code></pre>
<h3>方案二:轮询等待时间寄存器稳定(更严谨)</h3>
<pre><code class="language-c">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);
}
</code></pre>
<hr />
<h2>总结</h2>
<table>
<thead>
<tr>
<th>关键点</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>问题原因</strong></td>
<td>RTC 时间寄存器写入后,需要 2 个 32768Hz 时钟周期(约 61μs)才能稳定反映到读取寄存器</td>
</tr>
<tr>
<td><strong>SETRTC 清0 的含义</strong></td>
<td>仅表示"写入请求已同步到 RTC 模块",不代表"时间寄存器已更新完成"</td>
</tr>
<tr>
<td><strong>推荐做法</strong></td>
<td>SETRTC 清0 后,加入至少 100μs 延时,或轮询确认时间寄存器值已更新</td>
</tr>
</tbody>
</table>
<p>如果您在实际测试中还有其它疑问,欢迎继续交流!</p>
<hr />
<p><a href="https://www.stcaimcu.com/plugin.php?id=twpx_xunsearch&mod=forum&q=https%3A%2F%2Fwww.stcaimcu.com%2Fthread-24957-1-1.html&f=_all&m=yes&syn=yes&s=relevance&fid=0">🔍 搜索 "https://www.stcaimcu.com/thread-24957-1-1.html"</a></p>
<p>⏱️ 查找用时 2.6s | 总回答用时 11.7s</p>
神农鼎 发表于 2026-7-20 11:19
您好!感谢您分享这个帖子。这是一个非常典型的 RTC 时间写入后立即读取失败 的问题,我来为您做详细的技术 ...
你说:
手册依据
我查阅了 STC32G 系列手册中关于 RTC 的章节(手册章节:"RTC实时时钟,年/月/日/时/分/秒"),其中明确说明:
RTC 模块使用 32768Hz 时钟(内部或外部低速晶振)进行工作。写入 RTC 寄存器时,需要等待同步完成。在 SETRTC 清0 后,建议等待至少 2 个 32768Hz 时钟周期(约 61μs)再读取时间寄存器,以确保数据已正确更新。
这段话是在哪找到的,第几页?
为何我的芯片手册里面,没有这句话。难道我用的芯片手册,不是最新版?
我的芯片手册,只有红框里面的表达:
这个表达很模糊。他说的这个30.5us, 到底指的是SETRTC清零后,还要延时30.5us?还是说 SETRTC清零本身需要30.5us?
梁工 发表于 2026-7-20 10:20
RTC写入是按32768Hz时钟来同步的,当你启动写入后,至少要等待2个327687时钟即60us之后再读取。 ...
手册里写的 需要1个 RTC时钟配置完成,,读取还要再等1个RTC时钟么?如果是真的是这样,请在手册中更新相关描述。{:4_171:} _奶咖君_ 发表于 2026-7-20 13:44
手册里写的 需要1个 RTC时钟配置完成,,读取还要再等1个RTC时钟么?如果是真的是这样,请在手册中更新相 ...
我是经验值,电路里是1个RTC时钟,但是如果你不能精确控制1个RTC时间并与RTC时钟同步,那就增加冗余时间,用2个RTC时钟,不要用得那么临界。 “我也是被手册坑到了。手册里面的表达很模糊。他说的这个30.5us, 到底指的是SETRTC清零后,还要延时30.5us?还是说 SETRTC清零本身需要30.5us?”
我的理解是从启动配置 SETRTC = 1 后到 SETRTC清零 的这段时间是 1个RTC时钟,也就是你说的 “SETRTC清零本身需要30.5us”。
但是 上面梁工说的 到读取 可能需要两个时钟。要不 你再测一测? 梁工 发表于 2026-7-20 15:16
我是经验值,电路里是1个RTC时钟,但是如果你不能精确控制1个RTC时间并与RTC时钟同步,那就增加冗余时间 ...
他这个轮询的RTC标志,,理论上来说,系统时钟远远高于RTC时钟,应该能理解成RTC的标志清零之后,立马被轮询到了,然后打印,从RTC设置完成 到 打印输出这里是否还是需要1个RTC时钟? _奶咖君_ 发表于 2026-7-20 15:46
他这个轮询的RTC标志,,理论上来说,系统时钟远远高于RTC时钟,应该能理解成RTC的标志清零之后,立马被 ...
打印动作本身跟RTC设置无关。
RTC从启动设置 到 设置完成,需要1个32768Hz的周期,设置动作由RTC模块的时钟同步处理,所以要等写入后才能读出正常。
页:
[1]
2