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

唤醒 = 复位重启

相关推荐
wxmtwfx3 小时前
littlefs 源码分析
单片机·littlefs·嵌入式文件系统
嵌入式小站4 小时前
STM32 零基础可移植教程 18:I2C 入门,先用扫描器找一找总线上有没有设备
chrome·stm32·嵌入式硬件
天涯铭6 小时前
深入浅出:单片机I/O口串联电阻选型
单片机·嵌入式硬件·io口串联电阻
国科安芯6 小时前
ASP7A84AS——航天级低噪声高PSRR线性稳压器
网络·单片机·嵌入式硬件·架构·安全性测试
普中科技7 小时前
【普中STM32F1xx开发攻略--标准库版】-- 第 42 章 STM32 内部 FLASH 实验
stm32·单片机·嵌入式硬件·开发板·普中科技·内部flash
不做无法实现的梦~7 小时前
CLion+pyocd配置教程
嵌入式硬件
破晓单片机9 小时前
012、STM32项目分享:智能台灯系统
stm32·单片机·嵌入式硬件
悠哉悠哉愿意9 小时前
【单片机复习笔记】十五届国赛复盘
笔记·单片机·嵌入式硬件·学习
是温不嗜温9 小时前
芯茂微 LP7012 双重过流保护机制拆解:DESAT 单次锁存 vs OCP 连续 5 次锁存有何区别?
嵌入式硬件·开闭原则·电源管理·电源芯片·ac-dc