RTC(实时时钟)
内置 RTC,提供日历时钟 + 秒中断,供数字时钟、模拟时钟、计数器、倒计时等控件使用。
一、读写时间
#include "rtc.h"
extern _calendar_obj calendar; // w_year / w_month / w_date / hour / min / sec / week
RTC_Get(); // 读硬件 → 刷新 calendar
LTPrintf("%04d-%02d-%02d %02d:%02d:%02d week=%d\r\n",
calendar.w_year, calendar.w_month, calendar.w_date,
calendar.hour, calendar.min, calendar.sec, calendar.week);
RTC_Set(2026, 10, 20, 14, 30, 0); // 设置时间
RTC_Get(); // 立即生效| 函数 | 说明 |
|---|---|
RTC_Get() |
读硬件刷新 calendar,返回天计数 |
RTC_Set(y,m,d,h,mi,s) |
设置时间 |
RTC_Set_alarm(tm) |
设闹钟 |
RTC_Get_Week(y,m,d) |
算星期 0~6 |
LT_RtcInit() |
初始化,main.c 里已调用 |
二、注意:年份有 2000 偏移
硬件只存「天计数 + 时:分:秒」,年月日是软件从 RTC_BASE_YEAR(rtc.h)换算的。
写到 UI 变量时,年要减 2000:
| 地址 | 内容 |
|---|---|
0x7002 |
年(存 年 − 2000,2026 → 0x001A) |
0x7003 ~ 0x7007 |
月 / 日 / 时 / 分 / 秒 |
0x7008 |
星期 |
RTC_Set() 内部会 +2000,用函数就不用管;直接写 UI 变量或上位机下发时要自己换算。
上位机写时间(0x7002 起连续 6 个字):
5A A5 11 10 70 02 00 1A 00 0A 00 14 00 0E 00 1E 00 00 70 3F
│ 年=26 月=10 日=20 时=14 分=30 秒=0
└ 首地址 0x7002,连续写 6 个字LEN = 1 + 2 + 12 + 2 = 0x11- 只改部分字段时改首地址与字数(只改时分秒 → 首地址
0x7005,3 个字)
这个坑很常见:写指令里第一个数据字容易被误写成数量(
0x0006),
正确应为年份偏移值。上面的帧已按 Modbus CRC16、低字节在前 校验。
三、秒中断:每秒刷新三个标志
// Function/rtc.c —— RTC_Handler(),IRQ 13(EIC_IT_RTC)
RTC->PRCSR = prcsr | (1 << 19); // 写 1 清标志
RTC_Get(); // 刷新 calendar
RTC_flag = 1; Clock_flag = 1; Count_flag = 1;| 标志 | 消费方 |
|---|---|
RTC_flag |
数字时钟 Widget/digitalClock.c |
Clock_flag |
模拟时钟 Widget/analogClock.c |
Count_flag |
计数器 / 倒计时 Widget/uiCounter.c、varCounter.c |
目前只开了秒中断(Sec_IEN)和闹钟(Ala_IEN),其余 Min_IEN/Hou_IEN/Day_IEN 是注释掉的。
中断里没有喂狗,往里加耗时逻辑时注意主循环是否还在喂,避免被复位。
四、改常用参数
| 需求 | 位置 |
|---|---|
| 首次上电默认时间 | rtc.c 里 if (timer.day == 0) 分支的 RTC_Set(...) |
| 闹钟时间 | RTC_Set_alarm(tm) |
| 开分钟中断 | 取消 LT_RtcInit() 里 Min_IEN 的注释,并在 RTC_Handler() 里加对应分支 |
五、改底层
RTC_Get()跨天才重算年月日(先减整年再减整月),时分秒每次刷新 —— 可放心高频调用- 改
PRCSR前必须解锁:RTC->PRKEYR = 0x5aa55aa5; - 主要寄存器:
PRT1R(天计数)、PRT2R(时/分/秒)、PRCSR(控制+状态)、PRKEYR(钥匙)、PRENR(总使能)
六、注意事项
| 项 | 说明 |
|---|---|
| 解锁 | 改 PRCSR 前必须写 PRKEYR = 0x5aa55aa5 |
| 清标志 | 写 1 清,不是写 0 |
| 年份 | UI 变量存的是 年 − 2000 |
| 分频 | rtc_wclk_div = SYS_CLOCK/10000000 - 1,主频变了自动算 |
| 看门狗 | 起振等待 3 s 内有喂狗;自行加长等待要补喂狗 |
| 掉电保持 | 依赖硬件备用电源;天计数为 0 会写默认时间 |
作者:罗珍雪 创建时间:2026-10-20 12:01
最后编辑:罗珍雪 更新时间:2026-11-02 20:02
最后编辑:罗珍雪 更新时间:2026-11-02 20:02