欢迎光临
我们一直在努力

F429-HAL-RTC闹钟(2026/8/11)

目录

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 闹钟响红灯闪。拔电重插——时间不丢。

赞(0)
未经允许不得转载:171主机测评 » F429-HAL-RTC闹钟(2026/8/11)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址