1. 设置RTC Alarm A每30秒触发
在STM32CubeMX中配置Alarm A每30秒触发的参数设置如下:
参数 | 设置值 | 说明 |
---|---|---|
Hours | 0 (任意值) | 小时字段被掩码,值不影响 |
Minutes | 0 (任意值) | 分钟字段被掩码,值不影响 |
Seconds | 30 | 关键值:设置触发秒数 |
Sub Seconds | 0 (任意值) | 子秒字段被掩码 |
Alarm Mask Date Week day | Enable (掩码) | 忽略日期/星期 |
Alarm Mask Hours | Enable (掩码) | 忽略小时 |
Alarm Mask Minutes | Enable (掩码) | 忽略分钟 |
Alarm Mask Seconds | Disable (不掩码) | 必须比较秒字段 |
Alarm Sub Second Mask | All masked (全掩码) | 忽略子秒 |
Alarm Date Week Day Sel | Date (任意) | 字段被掩码不影响 |
Alarm Date | 1 (任意值) | 字段被掩码不影响 |
原理说明:
- 仅比较秒字段(Seconds=30)
- 其他所有字段被掩码忽略
- 当RTC秒数到达30时触发闹钟
- 每60秒触发一次(00:00:30, 00:01:30...)
2. Alarm A触发执行流程
当Alarm A触发时:
RTC硬件 中断控制器 处理器 RTC_IRQHandler HAL_RTC_AlarmAEventCallback 用户代码 置位ALRAF标志位 RTC_ISR.ALRAF = 1 发送RTC全局中断请求 退出低功耗模式(若在Stop模式) 跳转到中断服务程序 检查中断源 清除ALRAF标志 执行用户回调函数 执行自定义处理逻辑 RTC硬件 中断控制器 处理器 RTC_IRQHandler HAL_RTC_AlarmAEventCallback 用户代码
关键点:
- 硬件自动置位
RTC_ISR
寄存器的ALRAF
标志 - 若已使能中断(
ALRAIE=1
),触发RTC全局中断 - CPU跳转到
RTC_IRQHandler
中断服务程序 - 必须手动清除ALRAF标志(否则只触发一次)
- 最终调用用户自定义的
HAL_RTC_AlarmAEventCallback
3. Stop模式+RTC唤醒完整实现
硬件配置
c
// 在STM32CubeMX中启用:
// [X] RTC
// [X] Alarm A
// [X] Wakeup using RTC alarm
代码实现
c
/* 配置Alarm A每30秒触发 */
void Configure_RTC_Alarm(void)
{
RTC_AlarmTypeDef sAlarm = {0};
sAlarm.AlarmTime.Hours = 0;
sAlarm.AlarmTime.Minutes = 0;
sAlarm.AlarmTime.Seconds = 30; // 关键:设置30秒触发
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY |
RTC_ALARMMASK_HOURS |
RTC_ALARMMASK_MINUTES; // 掩码日/时/分
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL; // 掩码所有子秒
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDate = 1;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
{
Error_Handler();
}
}
/* 进入Stop模式 */
void Enter_Stop_Mode(void)
{
// 配置唤醒源
HAL_PWREx_EnableWakeUpPin(PWR_WAKEUP_PIN1); // 启用RTC唤醒
// 挂起滴答定时器
HAL_SuspendTick();
// 清除所有挂起的中断
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
// 进入Stop模式(保留SRAM和寄存器)
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// 唤醒后恢复系统时钟
SystemClock_Config();
// 恢复滴答定时器
HAL_ResumeTick();
}
/* RTC Alarm A回调函数 */
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
// 用户自定义处理逻辑
// 例如:点亮LED或处理数据
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
/* 主函数流程 */
int main(void)
{
HAL_Init();
SystemClock_Config();
// 初始化RTC
MX_RTC_Init();
Configure_RTC_Alarm();
// 启用RTC中断
HAL_NVIC_SetPriority(RTC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(RTC_IRQn);
while (1)
{
// 正常运行时执行任务...
// 当需要低功耗时
Enter_Stop_Mode();
// 唤醒后继续执行...
}
}
执行流程
是 主程序运行 调用Enter_Stop_Mode 配置唤醒源 挂起滴答定时器 进入Stop模式 RTC Alarm触发? 唤醒处理器 恢复系统时钟 恢复滴答定时器 执行RTC中断服务程序 调用用户回调函数
关键配置说明
-
唤醒源配置:
cHAL_PWREx_EnableWakeUpPin(PWR_WAKEUP_PIN1);
- 使能RTC Alarm作为唤醒源
-
低功耗模式选择:
cHAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
PWR_LOWPOWERREGULATOR_ON
:保持低功耗稳压器PWR_STOPENTRY_WFI
:使用WFI指令进入停止模式
-
时钟恢复:
cSystemClock_Config(); // 唤醒后必须重新配置时钟
- 退出Stop模式后系统时钟会复位为MSI(4MHz)
- 需要重新配置主时钟(HSI/HSE/PLL)
-
中断处理:
c// stm32l0xx_it.c中 void RTC_IRQHandler(void) { HAL_RTC_IRQHandler(&hrtc); }
- HAL库自动处理标志位清除
- 最终调用用户回调函数
4. 功耗优化技巧
-
最小化唤醒时间:
cvoid HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) { // 只执行最必要的操作 wakeup_flag = true; // 设置标志位 }
在主循环中处理复杂任务
-
快速返回低功耗:
cwhile(1) { if(wakeup_flag) { ProcessData(); // 处理数据 wakeup_flag = false; } Enter_Stop_Mode(); // 立即返回低功耗 }
-
RTC校准:
- 使用
HAL_RTCEx_SetSmoothCalib()
提高计时精度 - 尤其在使用LSI作为时钟源时
- 使用
-
备份域保护:
cHAL_PWR_EnableBkUpAccess(); // 访问RTC前启用 HAL_PWR_DisableBkUpAccess(); // 完成后禁用
通过此配置,系统将在Stop模式下消耗约1μA电流,每30秒唤醒一次执行任务,实现超低功耗运行。