3. RTC定时唤醒周期性任务
任务定义
本案例要求MCU在低功耗模式下,依靠RTC周期性中断实现定时唤醒,每次唤醒后执行一次传感器数据采集(以读取内部温度传感器代替外部传感器),随后重新进入低功耗,形成完整的“休眠—唤醒—采集—再休眠”循环。通过LED翻转指示唤醒事件发生,便于观测验证。
硬件连接与原理
- MCU:STM32L431(Cortex-M4,支持STOP2低功耗模式)
- RTC:LSE 32.768kHz晶振,配置为周期唤醒中断(WakeUp Timer)
- 内部温度传感器:ADC通道17,无需外部接线
- LED:PB2,唤醒后翻转一次,用于指示唤醒事件
- 按键:PA0(外部中断EXTI0),用于手动触发一次唤醒,便于快速验证
唤醒时序:MCU进入STOP2模式 → RTC计数溢出产生唤醒事件 → 系统时钟恢复 → 执行ADC采集 → 翻转LED → 再次进入STOP2
代码实现
以下代码基于STM32CubeMX生成的HAL工程,核心逻辑位于main.c中。RTC配置为LSE时钟源,唤醒周期设为5秒。
/* main.c 核心代码 */
#include "main.h"
#include "adc.h"
#include "rtc.h"
#include "gpio.h"
/* 私有变量 */
static uint32_t wakeup_count = 0; /* 唤醒次数计数 */
static uint16_t temp_raw = 0; /* ADC原始值 */
/* 函数声明 */
void SystemClock_Config(void);
void Enter_Stop2_Mode(void);
void Read_Temperature(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
/* 初始化外设 */
MX_GPIO_Init();
MX_ADC1_Init();
MX_RTC_Init();
/* 使能RTC唤醒中断 */
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5000, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
/* 5000 × (1/32768×16) ≈ 2.44秒,实际唤醒周期约2.44秒 */
/* 初始LED状态 */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
while (1)
{
/* 进入STOP2低功耗模式 */
Enter_Stop2_Mode();
/* 唤醒后执行:读取温度并翻转LED */
Read_Temperature();
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2);
wakeup_count++;
}
}
/**
* @brief 进入STOP2模式
*/
void Enter_Stop2_Mode(void)
{
/* 确保RTC唤醒中断已使能 */
HAL_SuspendTick(); /* 暂停SysTick,避免唤醒后时钟混乱 */
/* 进入STOP2模式 */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
/* 唤醒后重新配置系统时钟 */
SystemClock_Config();
HAL_ResumeTick();
}
/**
* @brief 读取内部温度传感器
*/
void Read_Temperature(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/* 配置ADC通道17(内部温度传感器) */
sConfig.Channel = ADC_CHANNEL_17;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_39CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/* 启动ADC转换 */
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
temp_raw = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
/* 温度计算:V25=0.76V,Avg_Slope=2.5mV/°C */
/* 实际温度 = (VADC - V25)/Avg_Slope + 25 */
}
/**
* @brief RTC唤醒中断回调(在stm32l4xx_it.c中调用)
*/
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
/* 清除唤醒标志由HAL库自动处理 */
/* 此回调在中断上下文中执行,仅做标志操作 */
/* 实际采集工作放在主循环中执行 */
}
/**
* @brief EXTI0中断回调(PA0按键)
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0)
{
/* 按键唤醒后,主循环会执行一次采集 */
/* 无需额外处理 */
}
}
关键配置说明
| 配置项 | 值 | 说明 |
|---|---|---|
| RTC时钟源 | LSE 32.768kHz | 低功耗模式下保持运行 |
| 唤醒时钟分频 | RTC_WAKEUPCLOCK_RTCCLK_DIV16 | 实际计数时钟 = 32768/16 = 2048Hz |
| 唤醒计数值 | 5000 | 唤醒周期 ≈ 5000/2048 ≈ 2.44秒 |
| 低功耗模式 | STOP2 | 保留RTC和备份域供电 |
| ADC通道 | 17(内部温度) | 无需外部传感器 |
编译与烧录
- 使用STM32CubeMX生成工程,勾选RTC、ADC1、GPIO外设
- 在
stm32l4xx_it.c中确保调用HAL_RTCEx_WakeUpTimerIRQHandler(&hrtc) - 编译工程:
make或使用IDE(Keil/IAR) - 烧录:
STM32_Programmer_CLI -c port=SWD -w build/main.hex
验证方法
判定标准:观察PB2连接的LED以约2.44秒为周期闪烁,每次闪烁代表一次RTC唤醒并完成ADC采集。可通过以下方式进一步验证:
- 在
Read_Temperature()中设置断点,每次唤醒后应触发一次 - 查看
temp_raw变量值,应随环境温度变化(范围约1000~1800) - 按下PA0按键可立即触发一次唤醒,LED应快速翻转一次
- 测量整机功耗:STOP2模式下电流应低于10μA(典型值)
预期输出:LED以约2.44秒间隔持续闪烁;wakeup_count变量每唤醒一次增加1;temp_raw值在室温下约为1300±200(具体值取决于芯片个体差异)。