当前位置: 首页 > article >正文

嵌入式系统应用-拓展-STM32 低功耗设计

STM32 低功耗设计

  • 1 低功耗介绍
    • 1.1 睡眠模式(Sleep Mode)
    • 1.2 停止模式(Stop Mode)
    • 1.3 待机模式(Standby Mode)
  • 2 代码编写
    • 2.1 进入睡眠模式
      • 2.1.1代码说明
      • 2.1.2 参考代码
      • 2.1.3 功耗优化建议
    • 2.2 停止模式
      • 2.2.1 代码说明
      • 2.2.2 代码编写
      • 2.2.3 代码优化建议
    • 2.3 待机模式
      • 2.3.1 代码说明
      • 2.3.2 代码编写
      • 2.3.3 优化建议
  • 3 总结

1 低功耗介绍

在手持设备使用过程中,功耗一直是一个比较敏感的问题。 如何优化低功耗设计,以下有几个方案:

1. 关闭未使用的外设时钟

通过 RCC_AHB1ENR、RCC_APB1ENR 等寄存器禁用不需要的外设时钟。

2. 降低主频

降低系统时钟频率(如使用 HSI 或 MSI 时钟源代替 HSE)。

3. 配置 GPIO 为低功耗状态

未使用的 GPIO 设置为模拟输入(高阻态)或输出低电平。

4. 使用 RTC 和低功耗定时器

利用 RTC 或 LPTIM(低功耗定时器)唤醒系统,替代普通定时器。

5. 电源管理

使用低功耗稳压器(如 STM32F407 支持电压调节范围)。

1.1 睡眠模式(Sleep Mode)

进入方式:通过执行 WFI(Wait for Interrupt)或 WFE(Wait for Event)指令。

功耗:内核停止运行,但外设(如 GPIO、定时器、UART 等)仍可工作。

唤醒方式:任何中断或事件均可唤醒。

1.2 停止模式(Stop Mode)

进入方式:通过配置电源控制寄存器(PWR_CR)进入。

功耗:关闭内核和大部分外设的时钟,仅保留 SRAM 和寄存器内容。

唤醒方式:

  1. 外部中断(EXTI)

  2. RTC 闹钟

  3. USB 唤醒信号等

注意:退出后需要重新配置时钟(HSI 作为默认时钟源)。

1.3 待机模式(Standby Mode)

进入方式:通过配置 PWR_CR 寄存器的 PDDS 位和 SLEEPDEEP 位。

功耗:最低功耗模式,关闭所有时钟(包括 SRAM),仅备份域(RTC、备份寄存器)可工作。

唤醒方式:

1.1 外部复位(NRST 引脚)

1.2 RTC 闹钟

1.2 独立看门狗(IWDG)

1.3 WKUP 引脚上升沿

注意:退出后相当于系统复位,程序从头开始执行

2 代码编写

2.1 进入睡眠模式

2.1.1代码说明

  1. 进入睡眠模式(内核停止,外设可选运行)。

  2. 通过 PA0(WKUP 引脚)的上升沿 触发外部中断(EXTI)唤醒。

  3. 唤醒后继续执行主程序。

2.1.2 参考代码

  1. 发送指令进入睡眠模式
// 进入睡眠模式
Enter_Sleep_Mode();
void Enter_Sleep_Mode(void) {
    // 执行 WFI(Wait For Interrupt),进入睡眠模式
    __WFI();
}
  1. 配置wakeup指令进入中断

// 配置 EXTI 中断(PA0 上升沿触发)
void EXTI_Configuration(void) {
    EXTI_InitTypeDef EXTI_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    
    // 连接 PA0 到 EXTI0
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
    
    // 配置 EXTI0 为上升沿触发
    EXTI_InitStruct.EXTI_Line = EXTI_Line0;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);
    
    // 配置 NVIC(设置中断优先级)
    NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
}

// EXTI0 中断服务函数(唤醒后自动执行)
void EXTI0_IRQHandler(void) {
    if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
        // 清除中断标志
        EXTI_ClearITPendingBit(EXTI_Line0);
        
        // 唤醒后无需额外操作,系统会继续执行主循环
    }
}

2.1.3 功耗优化建议

在进入睡眠模式前关闭不必要的外设时钟(如 ADC、UART 等)。
将未使用的 GPIO 设置为模拟输入(高阻态)。
如果无需快速唤醒,可以降低系统时钟频率(如切换至 HSI)。

一般情况下,电流从几百mA降低到10或者20mA左右。

2.2 停止模式

2.2.1 代码说明

  1. 更低功耗(典型值约 1~2 μA,具体取决于外设状态)。

  2. 内核停止,SRAM 和寄存器内容保留。

  3. 唤醒后需重新配置时钟(默认切换为 HSI 时钟源)

2.2.2 代码编写

  1. 发送指令,进入停止模式
// 进入停止模式(最低功耗,保留 SRAM)
void Enter_Stop_Mode(void) {
    // 使能 PWR 时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
    
    // 设置电压调节器为低功耗模式(进一步降低功耗)
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}
  1. 配置唤醒中断
void EXTI_Config(void) {
    EXTI_InitTypeDef EXTI_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    
    // 连接 PA0 到 EXTI0
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
    
    // 设置 EXTI0 为上升沿触发
    EXTI_InitStruct.EXTI_Line = EXTI_Line0;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);
    
    // 配置 NVIC 中断
    NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
}

// EXTI0 中断服务函数(唤醒时不需额外操作)
void EXTI0_IRQHandler(void) {
    if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
        EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志
    }
}
  1. 重新配置时钟
// 唤醒后重新配置时钟(Stop 模式会复位为 HSI)
void Clock_Reconfig(void) {
    // 重新启用 HSE 和 PLL
    RCC_HSEConfig(RCC_HSE_ON);
    while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
    
    RCC_PLLConfig(RCC_PLLSource_HSE, 8, 336, 2, 7); // 168MHz 配置
    RCC_PLLCmd(ENABLE);
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
    
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    while (RCC_GetSYSCLKSource() != 0x08);
}

2.2.3 代码优化建议

  1. 更低功耗配置

进入停止模式前调用 PWR_Regulator_LowPower,进一步降低稳压器功耗。

关闭所有不必要的外设时钟(如 RCC_AHB1PeriphClockCmd 仅启用 GPIOA 和 GPIOD)。

  1. 唤醒后时钟恢复

停止模式会复位系统时钟为 HSI(16MHz),需手动重新配置为 HSE+PLL(168MHz)。

  1. GPIO 状态优化

PA0 设置为 内部上拉,避免悬空误触发。

未使用的 GPIO 应设为 模拟输入(代码中未体现,实际需补充)。

4 功耗

停止模式 1~2 μA

2.3 待机模式

2.3.1 代码说明

  1. 最低功耗(约 2μA)。

  2. 完全关闭内核和大部分外设,仅备份域(RTC、备份寄存器)可选保持。

  3. 唤醒后系统复位(程序从头执行)。

  4. 唤醒源:WKUP 引脚(PA0)上升沿,RTC 闹钟事件,NRST 引脚外部复位,独立看门狗(IWDG)复位。

  5. 调用 PWR_EnterSTANDBYMode() 后,系统立即进入待机模式。需提前使能 PWR_WakeUpPin_1(对应 PA0)。

  6. 唤醒后程序 从头开始执行(相当于复位),可通过 PWR_GetFlagStatus(PWR_FLAG_SB) 检测是否从待机模式唤醒。需手动清除唤醒标志 PWR_ClearFlag(PWR_FLAG_SB)。

  7. PA0(WKUP 引脚)必须配置为 无内部上下拉(GPIO_PuPd_NOPULL),由外部电路确保明确电平。未使用的 GPIO 应设为 模拟输入 以降低漏电流

2.3.2 代码编写

  1. 进入待机模式
// 进入待机模式(通过 WKUP 引脚或 RTC 唤醒)
void Enter_Standby_Mode(void) {
    // 使能 PWR 时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
    
    // 使能 WKUP 引脚唤醒功能(PA0 上升沿)
    PWR_WakeUpPinCmd(PWR_WakeUpPin_1, ENABLE);
    
    // 清除唤醒标志(避免误触发)
    PWR_ClearFlag(PWR_FLAG_WU);
    
    // 进入待机模式
    PWR_EnterSTANDBYMode();
}
  1. PA0 配置输入口,不需要中断;但是需要注意事情是,需要外部电路确定IO的电平。一个上升沿就可以触发复位。

2.3.3 优化建议

  1. 关闭所有外设时钟,在进入待机模式前关闭不必要的时钟(如 ADC、USART 等);
  2. 配置 GPIO 为模拟输入,将所有未使用的 GPIO 设置为模拟输入(高阻态);
  3. 由于待机模式唤醒后程序会复位,若需保存状态,可使用:
  4. 备份寄存器(Backup Registers)(需启用 RCC_APB1Periph_BKP 时钟)。RTC 数据寄存器(需配置 RTC 和备份域)

3 总结

  1. 功耗对比图
    在这里插入图片描述

2 . STM32F4系列 不是专为低功耗设计,如需极低功耗,建议选择 STM32L 系列(如 STM32L4)。退出待机模式后,程序会从头执行(相当于复位)。在停止模式下,部分外设需要重新初始化。通过合理配置低功耗模式,STM32F407 可以用于电池供电或间歇性工作的场景。


http://www.kler.cn/a/600843.html

相关文章:

  • unittest自动化测试实战
  • 【ESP32S3】esp32获取串口数据并通过http上传到前端
  • Docker 搭建 PlantUML 服务:高效生成 UML 图的最佳实践
  • 36.评论日记
  • QT原子变量:QAtomicInteger、QAtomicPointer、QAtomicFlag
  • Win11 环境使用WSL安装Ubunut系统
  • winstart.wsf 病毒清理大作战
  • “需求引致供给“在互联网时代的范式重构:基于开源AI智能名片链动2+1模式S2B2C商城小程序源码的技术经济学分析
  • 计算机网络 --应用层
  • 【设计模式】深入解析装饰器模式(Decorator Pattern)
  • 什么是Dify,以及我们能用它来做什么
  • Docker镜像相关命令(Day2)
  • 【leetcode hot 100 394】字符串解码
  • 【ARM】MDK-解决单机版LIC获取报错
  • 05、Tools
  • JupyterLab 导出中文 PDF 方案
  • 《算法笔记》9.6小节 数据结构专题(2)并查集 问题 D: More is better
  • 特殊行车记录仪DAT视频丢失的恢复方法
  • 日志截断/日志中途清空/不停止程序
  • PLC物联网网关是什么?PLC网关应用场景