这一章在干嘛? RTC 实验:后备供电、BKP 寄存器、Calendar 时分秒 + 32.768 kHz 晶振校准、闹钟唤醒。从此 MCU 知道今天星期几。
22.1 RTC 时钟简介
RTC(Real Time Clock)= 实时时钟。
- 时钟源:LSE 32.768 kHz(外部晶振)或 LSI 32 kHz;
- 后备供电:VBAT 引脚接纽扣电池,掉电后继续走;
- 内部:BCD 编码的秒/分/时/日/月/年 + 星期计算器。
原书图 22.1.1:RTC 框图
后备域寄存器:
- RTC 自身寄存器;
- 20 个 BKP 寄存器(共 80 字节),掉电保持。
纽扣电池 CR2032:3V 锂电池,给 VBAT 供电,断电仍能走 RTC。
22.2 硬件设计
- LSE 晶振 PC14/PC15(开发板上 32.768 kHz);
- VBAT 已接 CR2032;
- 串口 1 输出时间。
22.3 程序设计
22.3.1 CubeMX 配置
- RCC → LSE = Crystal/Ceramic Resonator
- RTC → Activate Clock Source, Calendar, Tamper 等
- BKP 域访问使能(
HAL_PWR_EnableBkUpAccess(); __HAL_RCC_BKP_CLK_ENABLE();)
22.3.2 初始化 / 设置 / 读时间
RTC_TimeTypeDef t = {0};
RTC_DateTypeDef d = {0};
// 设置时间
t.Hours = 12; t.Minutes = 30; t.Seconds = 0;
HAL_RTC_SetTime(&hrtc, &t, RTC_FORMAT_BIN);
d.Year = 24; d.Month = 12; d.Date = 1;
HAL_RTC_SetDate(&hrtc, &d, RTC_FORMAT_BIN);
// 读时间
HAL_RTC_GetTime(&hrtc, &t, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &d, RTC_FORMAT_BIN); // 必须同时读 Date 否则 Time 不更新
printf("20%02d-%02d-%02d %02d:%02d:%02d\n", d.Year, d.Month, d.Date, t.Hours, t.Minutes, t.Seconds);
原书图 22.3.2.1:RTC 时间读写流程图
22.3.3 闹钟唤醒
配置 AlarmA 在指定时间触发中断,唤醒停止模式下的 MCU:
HAL_RTC_SetAlarm_IT(&hrtc, &a, RTC_FORMAT_BIN);
原书图 22.3.3.1:RTC 闹钟中断流程
22.4 下载验证
串口每 1s 打印当前时间;按 KEY_UP 设置时间 → 重启开发板 → 时间仍正确。
原书图 22.4.1:串口显示 RTC 时间
🧠 小测验RTC 时钟源选哪个?
LSE 32.768 kHz(精度最高)。
VBAT 的作用?
主电源断电后给 RTC 供电,保证时间继续走。
为什么 `HAL_RTC_GetTime` 后必须调 `HAL_RTC_GetDate`?
内部影子寄存器机制,不读 Date Time 不会更新。