【STM32 + CubeMX 教程】RTC 实时时钟 之 闹钟唤醒 -- F407篇

上一篇教程,我们已经实现了RTC双闹钟功能(固定时间闹钟A、相对时间闹钟B),能够通过串口查看闹钟触发提示。

本篇将在此基础上,进一步实现 RTC闹钟唤醒功能------让STM32进入低功耗模式(STOP模式),通过RTC闹钟触发中断,唤醒单片机继续运行,适用于电池供电、低功耗需求的场景(如便携设备、智能监测设备)。

STM32F407的RTC闹钟,支持唤醒低功耗模式,核心原理:单片机进入低功耗模式后,CPU停止工作,仅RTC外设由纽扣电池供电运行;当闹钟触发时,RTC产生中断,唤醒CPU恢复正常工作,既节能又能保证定时任务正常执行。

示范效果

  1. 单片机初始化后,配置闹钟A(如每天6:30:00)或闹钟B(如当前时间+10秒);

  2. 单片机进入STOP低功耗模式,CPU停止工作,功耗降至最低;

  3. 闹钟触发时,RTC中断唤醒单片机,执行闹钟任务(如串口打印、LED翻转);

  4. 任务执行完成后,可再次进入低功耗模式,实现"唤醒-执行-休眠"循环。

目录


一、工程准备

1. 基础前提

已完成前两篇教程(RTC日历功能、RTC双闹钟功能),确保RTC初始化、闹钟A/B配置、中断回调函数可正常运行;

2. 硬件准备

STM32F407开发板、USB-TTL串口、纽扣电池(CR2032,保证RTC掉电后正常运行)、LED灯(可选,用于直观显示唤醒状态);

3. 软件准备

Keil5、CubeMX、串口助手。

提示:若未完成前序教程,请先查阅:

① 【STM32 + CubeMX 教程】RTC 实时时钟 之 日历 -- F407篇

② 【STM32 + CubeMX 教程】RTC 实时时钟 之 双闹钟 -- F407篇


二、CubeMX 配置(低功耗+RTC闹钟唤醒)

本步骤在之前RTC双闹钟配置的基础上,新增"低功耗模式"和"唤醒源"配置,无需重新配置RTC闹钟核心参数,仅补充以下设置。

步骤 2-1:配置低功耗模式(STOP模式)

  1. 打开之前的CubeMX工程(已配置RTC日历+双闹钟);

  2. 点击左侧 Power Management(电源管理),展开配置;

  3. 选择 Stop mode(STOP模式),这是STM32F407最常用的低功耗模式(CPU停止,外设可选择性工作,RTC正常运行);

  4. 唤醒方式:勾选 Wake-up from Stop mode by RTC闹钟(允许RTC闹钟唤醒STOP模式);

  5. 其他默认即可(无需修改RTC相关配置,沿用之前的闹钟A/B配置)。

步骤 2-2:配置唤醒相关中断(关键)

  1. 点击左侧 NVIC(中断控制器);

  2. 找到 RTC Alarm global interrupt(RTC闹钟全局中断),确保已打勾使能(之前配置闹钟时已开启,此处确认即可);

  3. 优先级配置:默认即可(无需修改,若有其他中断可调整,确保RTC闹钟中断优先级高于低功耗唤醒中断)。

步骤 2-3:生成初始化代码

点击右上角 Generate Code 按钮,CubeMX会自动将低功耗模式、RTC唤醒相关配置添加到工程中,覆盖原有初始化代码(保留之前的用户代码,无需担心丢失)。


三、实现 RTC 闹钟唤醒功能(代码编写)

核心思路:初始化RTC闹钟 → 配置低功耗模式 → 单片机进入STOP模式 → 闹钟触发中断唤醒 → 执行任务 → 再次进入低功耗模式(循环)。

所有代码均在 main.c 中编写,沿用之前的闹钟A/B配置函数、中断回调函数,仅新增"低功耗配置函数"和"唤醒逻辑"。

步骤 3-1:编写低功耗配置函数(进入STOP模式)

打开 main.c 文件,在 /* USER CODE BEGIN 0 */ 和 /* USER CODE END 0 */ 之间,添加低功耗模式配置函数:

/******************************************************************************

* 函 数: RTC_EnterStopMode

* 功 能: 配置并进入STOP低功耗模式,由RTC闹钟唤醒

* 说 明: 1. 进入STOP模式后,CPU停止工作,RTC、串口等外设停止运行

* 2. 仅RTC外设由纽扣电池供电,维持闹钟计时

* 3. 闹钟触发后,自动唤醒CPU,恢复正常运行

* 参 数: 无

* 返回值: 无

* 备 注: 最后修改_2026年03月17日

******************************************************************************/

void RTC_EnterStopMode(void)

{

/* 关闭所有不必要的外设(可选,进一步降低功耗)*/

HAL_UART_DeInit(&huart1); // 关闭串口1(唤醒后需重新初始化)

/* 进入STOP模式 */

HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

// 说明:PWR_LOWPOWERREGULATOR_ON:低功耗稳压器开启(保证唤醒稳定)

// PWR_STOPENTRY_WFI:进入停止模式,等待中断唤醒(WFI = Wait For Interrupt)

/* 唤醒后,重新初始化被关闭的外设 */

MX_USART1_UART_Init(); // 重新初始化串口1,用于打印唤醒提示

}

步骤 3-2:修改中断回调函数(唤醒后执行任务)

唤醒后,程序会自动进入闹钟中断回调函数,我们在回调函数中执行任务(如打印提示、LED翻转),无需额外处理唤醒逻辑。

沿用之前的回调函数,补充唤醒任务(以LED翻转为例,若没有LED可仅保留串口打印):

  1. 闹钟A回调函数(固定时间唤醒)

/******************************************************************************

* 函 数: HAL_RTC_AlarmAEventCallback

* 功 能: RTC 闹钟 A 中断回调函数(唤醒后执行)

* 说 明: 1. 闹钟A触发时,唤醒单片机,自动调用此函数

* 2. 执行唤醒任务后,可再次进入低功耗模式

* 参 数: hrtc:RTC句柄

* 返回值: 无

* 备 注: 最后修改_2026年03月17日

******************************************************************************/

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)

{

/* 唤醒任务:串口打印 + LED翻转(LED引脚需自行定义,此处以PB0为例)*/

printf("闹钟A 唤醒成功!当前时间:6:30:00 \r\n");

HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); // 翻转LED状态,直观显示唤醒

/* 任务执行完成后,再次进入低功耗模式,等待下次闹钟唤醒 */

RTC_EnterStopMode();

}

  1. 闹钟B回调函数(相对时间唤醒)

/******************************************************************************

* 函 数: HAL_RTCEx_AlarmBEventCallback

* 功 能: RTC 闹钟B 中断回调函数(唤醒后执行)

* 说 明: 1. 闹钟B触发时,唤醒单片机,自动调用此函数

* 2. 重新设置闹钟B(5秒后再次触发),循环唤醒

* 参 数: hrtc:RTC句柄

* 返回值: 无

* 备 注: 最后修改_2026年03月17日

******************************************************************************/

void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)

{

/* 唤醒任务:串口打印 + LED翻转 */

printf("闹钟B 唤醒成功!将在5秒后再次唤醒 \r\n");

HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);

/* 重新设置闹钟B(5秒后触发),并再次进入低功耗模式 */

RTC_SetAlarmB(5);

RTC_EnterStopMode();

}

步骤 3-3:LED引脚配置(可选,直观显示唤醒)

若需要用LED显示唤醒状态,需在CubeMX中新增GPIO配置,步骤如下:

  1. 点击左侧 GPIO,选择一个空闲引脚(如PB0);

  2. 配置为 Output Push-Pull(推挽输出),默认电平设置为Low;

  3. 重新生成代码,CubeMX会自动生成GPIO初始化函数 MX_GPIO_Init(),无需手动编写。

步骤 3-4:main函数调用(初始化+进入低功耗)

在 /* USER CODE BEGIN 2 */ 和 /* USER CODE END 2 */ 之间,添加闹钟配置和低功耗调用代码,完整如下:

/* USER CODE BEGIN 2 */

printf("RTC闹钟唤醒功能初始化完成!\r\n");

// 配置闹钟A(每天6:30:00唤醒)

RTC_SetAlarmA(6, 30, 00);

// 配置闹钟B(首次5秒后唤醒,后续循环5秒唤醒)

RTC_SetAlarmB(5);

// 初始化完成后,进入低功耗模式,等待闹钟唤醒

RTC_EnterStopMode();

/* USER CODE END 2 */

步骤 3-5:烧录 & 验证

  1. 编译工程,将代码烧录到STM32F407开发板;

  2. 打开串口助手(波特率、数据位等参数与串口配置一致);

  3. 观察现象:

① 烧录后,串口打印"RTC闹钟唤醒功能初始化完成!",随后单片机进入低功耗模式;

② 闹钟A触发时(每天6:30:00),串口打印唤醒提示,LED翻转;

③ 闹钟B触发时(每5秒一次),串口打印唤醒提示,LED翻转,随后再次进入低功耗;

④ 若拔掉USB供电,仅靠纽扣电池,单片机仍能维持RTC运行,闹钟正常唤醒(实现低功耗节能)。


四、关键知识点(低功耗+唤醒原理)

  1. STOP低功耗模式说明

STM32F407的STOP模式,是兼顾"低功耗"和"唤醒速度"的最优选择,核心特点:

① CPU停止工作,内核时钟关闭,功耗降至几十微安(具体取决于外设关闭情况);

② RTC外设、后备域由纽扣电池供电,正常运行,维持日历和闹钟计时;

③ 可通过RTC闹钟、外部中断等方式唤醒,唤醒时间快(几微秒);

④ 唤醒后,CPU恢复正常运行,外设需重新初始化(如串口、GPIO)。

  1. RTC闹钟唤醒核心原理

① 单片机进入STOP模式后,仅RTC外设工作,不断检测闹钟触发条件;

② 当闹钟时间与当前RTC时间匹配时,RTC产生中断信号,触发NVIC中断;

③ 中断信号唤醒CPU,退出STOP模式,执行中断回调函数中的任务;

④ 任务执行完成后,可再次调用 RTC_EnterStopMode(),进入低功耗循环。

  1. 关键函数说明

① HAL_PWR_EnterSTOPMode():进入STOP低功耗模式,两个参数含义:

  • PWR_LOWPOWERREGULATOR_ON:开启低功耗稳压器,保证唤醒时电压稳定;

  • PWR_STOPENTRY_WFI:进入停止模式后,等待中断唤醒;

② HAL_UART_DeInit() / MX_USART1_UART_Init():关闭/重新初始化串口,降低功耗;

③ HAL_GPIO_TogglePin():翻转LED引脚电平,直观显示唤醒状态。


五、常见问题排查

  1. 进入低功耗后,闹钟无法唤醒

原因及解决方法:

① CubeMX未开启"RTC闹钟唤醒STOP模式":重新配置Power Management,勾选唤醒选项;

② RTC闹钟中断未使能:检查NVIC中"RTC Alarm global interrupt"是否打勾;

③ 纽扣电池没电:更换新的CR2032纽扣电池,确保RTC掉电后正常运行;

④ 唤醒后未重新初始化外设:确保 RTC_EnterStopMode() 中,唤醒后重新初始化串口、GPIO等。

  1. 唤醒后,串口打印乱码

原因:进入低功耗时关闭了串口,唤醒后未重新初始化串口。

解决:在 RTC_EnterStopMode() 中,唤醒后调用 MX_USART1_UART_Init(),重新初始化串口。

  1. 低功耗效果不明显

原因:未关闭不必要的外设(如LED、其他GPIO、串口)。

解决:在进入低功耗前,关闭所有不使用的外设(如 HAL_GPIO_DeInit() 关闭多余GPIO)。

  1. 闹钟唤醒后,无法再次进入低功耗

原因:回调函数中未调用 RTC_EnterStopMode(),或调用位置错误。

解决:在闹钟回调函数的最后,添加 RTC_EnterStopMode(),确保任务执行完成后进入低功耗。

总结

本篇教程在RTC双闹钟的基础上,实现了RTC闹钟唤醒低功耗功能,核心是"配置STOP模式+RTC闹钟中断唤醒",适用于电池供电、需要节能的场景。

重点注意:

① CubeMX中必须开启"RTC闹钟唤醒STOP模式"和RTC中断;

② 进入低功耗前关闭不必要的外设,唤醒后重新初始化;

③ 闹钟回调函数中,执行任务后需再次进入低功耗,实现循环唤醒。

至此,STM32F407 RTC的核心功能(日历、双闹钟、闹钟唤醒)已全部实现,可直接应用于实际项目开发。

相关推荐
梁朝辉7 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
省四收割者8 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
崇山峻岭之间9 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious9 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng13 小时前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计14 小时前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
kebidaixu14 小时前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片详解
stm32
kebidaixu15 小时前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片调试实录:四个关键问题与解决方案
stm32
KaifuZeng1 天前
通信与接口协议面试一、基本概念
嵌入式硬件·通信与接口协议