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();

唤醒 = 复位重启

相关推荐
FreakStudio5 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘10 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u1521096484910 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd84510150010 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼10 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
牛根生同志10 天前
SPI数据收发的时候 TXE与RXNE标志位置位的时机
stm32·spi·transfer
wohoo_wangzi10 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
goldenrolan10 天前
学习型红外控制系统稳定性挂测工装专项总结
软件测试·python·stm32·嵌入式·红外
✎ ﹏梦醒͜ღ҉繁华落℘10 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展10 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件