目录
1、RTC_CLK_Config — 时钟初始化
第一步:振荡器配置 RCC_OscInitTypeDef
第二步:外设时钟选择 RCC_PeriphCLKInitTypeDef
第三步:RTC 预分频 Rtc_Handle.Init
2、RTC_TimeAndDate_Set — 设时间日期
RTC_TimeTypeDef 时间结构体
RTC_DateTypeDef 日期结构体
HAL_RTC_SetTime/SetDate 第三个参数
3、RTC_AlarmSet — 闹钟配置
RTC_AlarmTypeDef 闹钟结构体
4、备份寄存器 HAL_RTCEx_BKUPWrite/Read
5、时间轴
一:RTC 闹钟实验 改动清单
rtc.h — 新增
rtc.c — 新增
main.c — 替换
stm32f4xx_hal_conf.h — 修改
Keil 工程 — 修改
1、RTC_CLK_Config — 时钟初始化
第一步:振荡器配置 RCC_OscInitTypeDef
osc.OscillatorType // ① 要操作哪种振荡器
osc.PLL.PLLState // ② PLL 状态(RTC 不用 PLL,关掉)
osc.LSEState // ③ LSE 开关
① OscillatorType = RCC_OSCILLATORTYPE_LSE
→ 告诉 HAL:我只配置 LSE,别的不动
→ 可选:LSI / HSI / HSE / LSE,可 | 组合
② PLLState = RCC_PLL_NONE
→ RTC 用 LSE 直接驱动,不经过 PLL
→ 如果设 RCC_PLL_ON,HAL 会去配 PLL,这里不需要
③ LSEState = RCC_LSE_ON
→ 打开外部 32.768KHz 晶振
→ RCC_LSE_OFF = 关,RCC_LSE_ON = 开
第二步:外设时钟选择 RCC_PeriphCLKInitTypeDef
clk.PeriphClockSelection // ④ 要配哪个外设的时钟
clk.RTCClockSelection // ⑤ RTC 时钟源选谁
④ PeriphClockSelection = RCC_PERIPHCLK_RTC
→ 告诉 HAL:我要配 RTC 的时钟
→ 可选:RCC_PERIPHCLK_RTC / I2S / LTDC / SAI / CK48 等
⑤ RTCClockSelection = RCC_RTCCLKSOURCE_LSE
→ RTC 的时钟哪来:外部 32.768KHz 晶振
→ 可选:LSE(外部高精度)/ LSI(内部低精度 ~32KHz)/ HSE/32
第三步:RTC 预分频 Rtc_Handle.Init
Rtc_Handle.Init.AsynchPrediv // ⑥ 异步预分频
Rtc_Handle.Init.SynchPrediv // ⑦ 同步预分频
Rtc_Handle.Init.HourFormat // ⑧ 时间制式
⑥ AsynchPrediv = 127
→ 异步分频器:(127+1) = 128 分频
→ LSE 32768 / 128 = 256Hz ← 这是"粗调",分频后给同步分频器
⑦ SynchPrediv = 255
→ 同步分频器:(255+1) = 256 分频
→ 256Hz / 256 = 1Hz ← "细调",最终 RTC 每秒加 1
⑧ HourFormat = RTC_HOURFORMAT_24
→ 24 小时制(0~23)
→ RTC_HOURFORMAT_12 = 12 小时制(AM/PM)
两个预分频串联:为什么不用一个大的?因为异步分频器功耗低但精度粗,同步分频器精度高但功耗大。HAL 用异步控制功耗,用同步控制精度。
2、RTC_TimeAndDate_Set — 设时间日期
RTC_TimeTypeDef 时间结构体
t.TimeFormat // ① 12/24 小时制
t.Hours // ② 时
t.Minutes // ③ 分
t.Seconds // ④ 秒
① TimeFormat = RTC_HOURFORMAT_24
→ 设的数是 24 小时制还是 12 小时制
→ RTC_HOURFORMAT_24:Hours=0~23
→ RTC_HOURFORMAT_12:Hours=1~12 + AM/PM 标志
② Hours = 12
→ 时,范围 0~23(24 小时制)或 1~12(12 小时制)
③ Minutes = 0
→ 分,范围 0~59
④ Seconds = 0
→ 秒,范围 0~59
RTC_DateTypeDef 日期结构体
d.WeekDay // ⑤ 星期
d.Date // ⑥ 日
d.Month // ⑦ 月
d.Year // ⑧ 年
⑤ WeekDay = 1
→ 星期几,范围 1~7
→ 1=周一 2=周二 … 7=周日(HAL 定义)
⑥ Date = 1
→ 日,范围 1~31(根据月份自动判上限)
⑦ Month = 1
→ 月,范围 1~12
→ RTC 的日历逻辑会自动处理闰年、大小月
⑧ Year = 26
→ 年,范围 0~99,对应 20YY
→ 26 = 2026 年
HAL_RTC_SetTime/SetDate 第三个参数
RTC_FORMAT_BIN // ⑨ 数据格式
⑨ RTC_FORMAT_BIN
→ 传进去的数是二进制值:t.Hours=12 → 寄存器存 12
→ RTC_FORMAT_BCD = BCD 编码:t.Hours=12 → 寄存器存 0x12
→ 一般用 BIN,跟直觉一致。BCD 是给老式 RTC 芯片兼容用的
3、RTC_AlarmSet — 闹钟配置
RTC_AlarmTypeDef 闹钟结构体
a.Alarm // ① 闹钟编号
a.AlarmTime.TimeFormat // ② 时制
a.AlarmTime.Hours/Minutes/Seconds // ③④⑤ 闹钟时刻
a.AlarmMask // ⑥ 匹配粒度
a.AlarmDateWeekDaySel // ⑦ 按日期还是星期匹配
a.AlarmDateWeekDay // ⑧ 匹配值
① Alarm = RTC_ALARM_A
→ F429 有闹钟 A 和闹钟 B 两个独立闹钟
→ RTC_ALARM_A = 第一个闹钟
② TimeFormat = RTC_HOURFORMAT_24
→ 闹钟时间用 24 小时制
③④⑤ Hours=12, Minutes=0, Seconds=30
→ 闹钟时刻:12 点 00 分 30 秒
⑥ AlarmMask = RTC_ALARMMASK_DATEWEEKDAY
→ 匹配粒度:按"日期"匹配(默认的秒/分/时也参与比较)
→ RTC_ALARMMASK_ALL:秒+分+时+日期全部匹配才触发
→ RTC_ALARMMASK_MINUTES:忽略秒,只比时分
→ RTC_ALARMMASK_HOURS:只比小时
→ RTC_ALARMMASK_NONE:啥都比(最严格)
⑦ AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE
→ ⑧ 里填的数字理解为"几号"还是"星期几"
→ RTC_ALARMDATEWEEKDAYSEL_DATE:匹配日期(1 号)
→ RTC_ALARMDATEWEEKDAYSEL_WEEKDAY:匹配星期(周一)
⑧ AlarmDateWeekDay = 1
→ 匹配值:1 号那天闹钟才响
4、备份寄存器 HAL_RTCEx_BKUPWrite/Read
RTC_BKP_DR0(备份域寄存器 0)
→ F429 有 20 个备份寄存器(DR0~DR19),每个 32 位
→ 存在 VBAT 域,只要纽扣电池有电,即使主电源断、芯片复位,数据也不丢
→ 我们的用法:写 0x32F2 → 标记"RTC 已初始化",下次上电跳过设时间
##
5、时间轴
上电
│
├─ ① RTC_CLK_Config()
│ LSE 晶振起振 → 128×256 预分频 → 1Hz 心跳 → 计数器开始走
│ (时间已存在 RTC 里没丢,RTC 继续从断电前时刻往后走)
│
├─ ② 检查备份寄存器
│ ├─ 首次(或电池断过)→ RTC_TimeAndDate_Set(12:00:00)
│ └─ 非首次 → 跳过设时间,RTC 继续走
│
├─ ③ RTC_AlarmSet()
│ 写闹钟时间 12:00:30 到闹钟 A 寄存器
│ 配 NVIC 中断 RTC_Alarm_IRQn
│
├─ ④ RTC_TimeAndDate_Show() 死循环
│
│ 每秒读当前时间 → 串口打印
│
│ 12:00:30 到了
│ ↓
│ RTC 硬件比较:当前时间 == 闹钟时间 → 触发中断
│ ↓
│ RTC_Alarm_IRQHandler → HAL_RTC_AlarmIRQHandler
│ ↓
│ HAL_RTC_AlarmAEventCallback ← 我们的回调
│ ↓
│ AlarmFlag = 1
│ ↓
│ RTC_TimeAndDate_Show 里检测到 AlarmFlag → 红灯闪 30 次
│
└─ 循环继续,时间继续走
一句话:RTC 一直在后台自己走,你只需要管三件事——设初值、定闹钟、读时间。
一:RTC 闹钟实验 改动清单
rtc.h — 新增
| 1-39 | 完整文件(39 行)。LSE 预分频宏(AsynchPrediv=127, SynchPrediv=255 → 1Hz)+ 默认时间/闹钟宏 + 备份寄存器宏 + 5 个函数声明 + Rtc_Handle 句柄导出 |
rtc.c — 新增
| 1-178 | 完整文件(178 行)。5 个函数,均含头注释(原型 + 形参[输入]/[输出] + 返值 + 调用示例)+ 行右侧 // 注释 |
| 18-47 | RTC_CLK_Config:开 PWR → 使能备份域 → 开 LSE → 选 LSE 为 RTC 时钟 → 配预分频(127+1)×(255+1)=1Hz |
| 63-82 | RTC_TimeAndDate_Set:HAL_RTC_SetTime + HAL_RTC_SetDate 写默认时间 → HAL_RTCEx_BKUPWrite 写 0x32F2 标记已初始化 |
| 98-143 | RTC_TimeAndDate_Show:while(1) 每秒 HAL_RTC_GetTime/GetDate → printf 串口打印 → AlarmFlag 触发红灯闪 30 次 |
| 157-174 | RTC_AlarmSet:配闹钟 A(时间+日期匹配)→ HAL_RTC_SetAlarm_IT → NVIC 使能 RTC_Alarm_IRQn |
| 176-178 | HAL_RTC_AlarmAEventCallback:闹钟中断回调 → AlarmFlag = 1 |
main.c — 替换
| 1-52 | 函数头注释 + HAL/LED/SysTick/UART 初始化 → RTC_CLK_Config() → HAL_RTCEx_BKUPRead 检测备份寄存器(≠0x32F2 首次设时间+闹钟 / 已配直接显示)→ RTC_TimeAndDate_Show() 死循环 |
stm32f4xx_hal_conf.h — 修改
| 61 | 取消注释 #define HAL_RTC_MODULE_ENABLED |
Keil 工程 — 修改
| 加源文件 | BSP/RTC/rtc.c |
| HAL 模块 | 确认 stm32f4xx_hal_rtc.c + stm32f4xx_hal_rtc_ex.c 在 Library 组 |
| Include Path | 加 BSP\\RTC |
编译下载。串口每秒打印时间,到 12:00:30 闹钟响红灯闪。拔电重插——时间不丢。






