You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在STM32 BluePill上实现固定周期从待机模式自动唤醒

STM32 BluePill(STM32F103)定时唤醒待机模式实现方案

实现原理

STM32待机模式下仅RTC、备份寄存器、待机电路保持供电,是功耗最低的休眠模式,和你之前ATmega328P的掉电休眠逻辑匹配。采用RTC闹钟作为唤醒源,即可实现固定间隔自动唤醒,无需操作系统支持。

STM32CubeMX 基础配置(图形化配置避免宏定义编译错误)

  • 时钟配置:开启LSE外部低速晶振(32.768kHz,RTC专用精度更高,没有硬件的话也可以选LSI内部低速时钟,精度稍差),RTC时钟源选择对应配置的LSE/LSI
  • RTC配置:开启「Alarm A」闹钟功能
  • PWR配置:开启RTC闹钟作为待机模式唤醒源
  • 其他外设配置:按需开启你用到的传感器接口、警报输出IO即可

可直接复用的代码实现

#include "stm32f1xx_hal.h"

// 直接引用CubeMX自动生成的RTC句柄即可
extern RTC_HandleTypeDef hrtc;

// 配置RTC闹钟,设定interval_s秒后触发唤醒
void set_rtc_wakeup(uint32_t interval_s)
{
    RTC_AlarmTypeDef sAlarm = {0};
    HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
    
    // 获取当前RTC时间
    RTC_TimeTypeDef sTime = {0};
    RTC_DateTypeDef sDate = {0};
    HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
    HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
    
    // 计算闹钟触发时间:当前时间 + 间隔秒数
    uint32_t total_sec = sTime.Hours * 3600 + sTime.Minutes * 60 + sTime.Seconds + interval_s;
    sAlarm.AlarmTime.Hours = (total_sec / 3600) % 24;
    sAlarm.AlarmTime.Minutes = (total_sec % 3600) / 60;
    sAlarm.AlarmTime.Seconds = total_sec % 60;
    sAlarm.Alarm = RTC_ALARM_A;
    sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY; // 仅匹配时间即可,忽略日期
    sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
    
    // 启动闹钟中断
    HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    __HAL_RTC_ALARM_ENABLE_IT(&hrtc, RTC_IT_ALRA);
}

// 进入待机模式函数,和你之前Arduino的休眠函数功能完全对应
void enter_standby(uint32_t wakeup_interval_s)
{
    // 先配置唤醒闹钟
    set_rtc_wakeup(wakeup_interval_s);
    
    // 关闭不必要外设降低功耗,对应你之前关闭ADC的操作
    // 用到ADC可以加:HAL_ADC_DeInit(&hadc);
    // 用到串口可以加:HAL_UART_DeInit(&huart1);
    
    // 进入待机模式
    HAL_PWR_EnterSTANDBYMode();
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_RTC_Init();
    // 其他外设初始化:比如ADC、传感器相关初始化
    
    // 待机唤醒后芯片相当于重启,会从main重新执行,和你之前Arduino的setup逻辑完全对齐
    uint16_t sensor_value = read_sensor(); // 替换为你自己的传感器读取函数
    if(sensor_value == 0)
    {
        turnOnAlarm(); // 替换为你自己的警报触发逻辑
        while(1); // 触发警报后停止休眠循环
    }
    
    // 否则设置4秒后唤醒继续循环,要改2秒直接传参数2即可
    enter_standby(4);
    
    // 代码不会执行到此处
    while(1);
}

// 示例:替换为你自己的传感器读取逻辑
uint16_t read_sensor(void)
{
    return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
}

// 示例:替换为你自己的警报触发逻辑
void turnOnAlarm(void)
{
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
}

注意事项

  • 待机模式唤醒后所有通用寄存器都会重置,不需要额外写loop函数,逻辑完全和你之前Arduino的实现对齐
  • 如果需要保留少量数据跨休眠周期,可以存储在RTC备份寄存器中,STM32F103最多支持20字节的备份存储
  • 没有外部32.768k晶振的场景,直接把RTC时钟源换成LSI内部时钟即可,不用修改业务代码,仅定时精度稍低

内容的提问来源于stack exchange,提问作者Tono Nam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 21:57:00