STM32 睡眠模式测试程序

基于 STM32F103 + HAL 库,代码可直接编译运行,并且教你如何测量电流验证是否真的睡下去了。


一、STM32 低功耗模式速查

模式 唤醒方式 唤醒后 典型功耗 适用场景
Sleep 任意中断 立即执行 mA 级 只是让 CPU 歇一下
Stop EXTI(按键) 需要重配时钟 μA 级 电池供电首选
Standby WakeUp 引脚 / RTC 相当于复位 < 5μA 极低功耗,但麻烦

90% 的项目用 Stop 模式就够了


二、Stop 模式测试程序

1、GPIO 设计

引脚 功能
PA0 唤醒按键(EXTI0)
PC13 LED(闪烁表示运行)
其余 IO 设为 Analog 省电

2、主程序(main.c)

c 复制代码
#include "main.h"

void SystemClock_Config(void);
void Enter_STOP_Mode(void);

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // PC13 LED
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    // PA0 唤醒按键
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

    while (1)
    {
        // 运行指示
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        HAL_Delay(200);

        // 运行 2 秒后进入 STOP
        static uint32_t cnt = 0;
        if (++cnt > 10)
        {
            cnt = 0;
            HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
            Enter_STOP_Mode();
        }
    }
}

3、进入 Stop 模式

c 复制代码
void Enter_STOP_Mode(void)
{
    __HAL_RCC_PWR_CLK_ENABLE();

    // 关闭所有不需要的外设时钟
    __HAL_RCC_USART1_CLK_DISABLE();
    __HAL_RCC_SPI1_CLK_DISABLE();
    __HAL_RCC_TIM2_CLK_DISABLE();

    // 配置所有 IO 为模拟输入(最省电)
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

    GPIO_InitStruct.Pin = GPIO_PIN_All;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    // 进入 STOP 模式,唤醒后使用 HSI
    HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
}

4、唤醒后恢复时钟

c 复制代码
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_0)
    {
        // 重新初始化系统时钟(STOP 唤醒后默认用 HSI)
        SystemClock_Config();

        // 重新初始化 GPIO
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_GPIOC_CLK_ENABLE();

        GPIO_InitTypeDef GPIO_InitStruct = {0};
        GPIO_InitStruct.Pin = GPIO_PIN_13;
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    }
}

三、SystemClock_Config(标准 72MHz)

c 复制代码
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK |
                                  RCC_CLOCKTYPE_HCLK |
                                  RCC_CLOCKTYPE_PCLK1 |
                                  RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
}

四、如何验证是否真的睡下去了

方法 1:万用表测电流(最准)

状态 电流
运行 10~30 mA
Sleep 5~10 mA
Stop ≈ 20~50 μA
Standby < 5 μA

如果 Stop 模式 > 1mA,一定有问题


2、方法 2:LED 行为

  • 运行:LED 快速闪烁
  • 睡眠:LED 熄灭
  • 唤醒:LED 再次闪烁

参考代码 睡眠模式测试程序 www.youwenfan.com/contentcsv/103598.html

五、常见问题

问题 原因
睡不下去 外设没关时钟
唤醒后死机 没重配系统时钟
电流很大 IO 没设为 Analog
自动唤醒 没关滴答定时器
串口失效 STOP 后 USART 时钟没了

六、彻底省电

关闭 SysTick 再睡

c 复制代码
HAL_SuspendTick();   // 禁止 SysTick
HAL_PWR_EnterSTOPMode(...);
HAL_ResumeTick();    // 恢复 SysTick

七、Standby 模式

c 复制代码
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
HAL_PWR_EnterSTANDBYMode();

唤醒 = 复位重启

相关推荐
沐欣工作室_lvyiyi8 分钟前
基于物联网的汽车智能座舱控制系统的设计和实现(论文+源码)
单片机·物联网·汽车·智能座舱·哈尔滨信息工程学院·黄河科技学院
创界工坊工作室9 分钟前
21-基于单片机的智能窗帘与光照联动控制系统设计
stm32·单片机·嵌入式硬件·proteus
zhaoshuzhaoshu21 分钟前
嵌入式系统看门狗详解——以 STM32 为例
stm32·嵌入式硬件
恒锐丰科技林技术员36 分钟前
EG2113D 高压半桥驱动芯片:高压功率变换的实用驱动方案
经验分享·嵌入式硬件·硬件工程
石马马户1 小时前
传感器的中断 Latch、中断状态寄存器、中断读取与保持时间
stm32·单片机·嵌入式硬件
fly_sunnn11 小时前
STM32-GPIO
stm32·单片机·嵌入式硬件
宵时待雨15 小时前
STM32基础1:嵌入式历史与生态
stm32·单片机·嵌入式硬件
zhangzhangkeji15 小时前
stm32 14-1 WDG 看门狗:理论部分
stm32
不会代码的小猴16 小时前
启动文件
stm32·嵌入式硬件
深圳老胡16 小时前
STM32CubeMX 生成 CMake 工程,用 VSCode 编译与调试的完整流程
笔记·stm32·单片机·代码规范