news 2026/4/18 3:43:41

32 低功耗模式(睡眠 停机 待机 )

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
32 低功耗模式(睡眠 停机 待机 )

一、前言

在实际嵌入式开发过程中,我们会去考虑我们设计出来的产品的实际工作时间,例如桥梁探测系统,智能穿戴设备,我们希望在满足用户前提下尽可能地减少用户充电次数,所以引出今日沟通的主题:低功耗模式。比如桥梁探测设备,在冬季不下雨的时候,设备就可以进入休眠模式,实时探测数据的时间间隔可以适当拉长。接下来我们一起来了解下三种模式。

1 电源控制

电源控制(PWR:Power Control)。电源对电子设备来说非常重要,它是保证系统稳定运行的基础。在保证系统能稳定运行的同时,对嵌入式设备一般又有低功耗的需求。

1.1电源框图

1)VDDA供电区域

主要负责模拟部分的供电。为了提高转换的精确度,ADC使用一个独立的电源供电,过滤和屏蔽来自印刷电路板上的毛刺干扰。主要给A/D转换器、温度传感器、复位模块、PLL等供电。

2)VDD供电区域

VDD是数字电的正极,VSS是数字电的负极,电压3.3V。给I/O电路、待机电路和电压调节器供电。

3)1.8V供电区域

CPU核心、内部存储器、内置的数字外设都是工作在1.8V的电压。1.8V的低电压是由从电压调节器得到的。

4)后备供电区域

VBAT引脚会接电池和其他电源,当VDD断电时,可以保存备份寄存器的内容和给RTC供电。

VBAT脚也为RTC、LSE振荡器和PC13至PC15供电,这保证当主要电源被切断时RTC能继续工作。

5)电压调节器

复位后,电压调节器总是工作使能的。有3种不同的工作模式:

  1. 运转模式:调节器以正常功耗模式提供1.8V电源(内核、内存和外设)2.
  2. 停止模式:调节器以低功耗模式提供1.8V电源,用于保存寄存器和SRAM的内容
  3. 待机模式:调节器停止供电。除了备用电路和备份域外,寄存器和SRAM的内容全部丢失。

1.2上电复位和掉电复位

类似于按键(有延迟),当VDD/VDDA低于指定的限位电压VPOR/VPDR时,系统保持为复位状态,而无需外部复位电路。

复位和解除复位有一个40mv的迟滞电压。当电压大于VPOR时解除复位,当电压小于VPDR时进入复位。设置2个阈值的作用是当电压在附近抖动的时候防止频繁的复位和解除复位。

1.3 低功耗

在系统或电源复位以后,微控制器处于运行状态。当CPU不需继续运行时,可以利用多种低功耗模式来节省功耗,例如等待某个外部事件时。

用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。

STM32F10xxx有三种低功耗模式:

1.3.1 睡眠模式

(1)睡眠模式
  1. SLEEP-NOW:如果SLEEPONEXIT位被清除,当WRI或WFE被执行时,微制器立即进入睡眠模式。
  2. SLEEP-ON-EXIT:如果SLEEPONEXIT位被置位,系统从最低优先级的中断处理程序中退出时,微控制器就立即进入睡眠模式。

注意:在睡眠模式下,所有的I/O引脚都保持它们在运行时的状态。验证:LED进入睡眠模式依然会亮

(2)退出睡眠模式

如果执行WFI指令进入睡眠模式,任意一个被嵌套向量中断控制器响应的外设中断都能将系统从睡眠模式唤醒。

如果执行WFE指令进入睡眠模式,则一旦发生唤醒事件时,微处理器都将从睡眠模式退出。

1.3.2停止模式

停止模式是在Cortex™-M3的深睡眠模式基础上结合了外设的时钟控制机制,在停止模式下电压调节器可运行在正常或低功耗模式。此时在1.8V供电区域的的所有时钟都被停止,PLL、HSI和HSE RC振荡器的功能被禁止,SRAM和寄存器内容被保留下来。

注意:在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态。

(1)进入停止模式

在停止模式下,通过设置电源控制寄存器(PWR_CR)的LPDS位使内部调节器进入低功耗模式,能够降低更多的功耗。

  1. 如果正在进行闪存编程,直到对内存访问完成,系统才进入停止模式。
  2. 如果正在进行对APB的访问,直到对APB访问完成,系统才进入停止模式。
(2)退出停止模式

1.3.3待机模式

待机模式可实现系统的最低功耗

该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个1.8V供电区域被断电。PLL、HSI和HSE振荡器也被断电。SRAM和寄存器内容丢失。只有备份寄存器和待机电路维持供电。这么说吧,能停的全停。

注意:在待机模式下,所有的I/O引脚处于高阻态,除了以下的引脚:

  1. 复位引脚(始终有效)
  2. 当被设置为防侵入或校准输出时的TAMPER引脚。
  3. 被使能的唤醒引脚。

二、代码介绍

1 睡眠模式

/** * 需求 : 测试STM32芯片进入低功耗 - 睡眠模式 */ /** * 睡眠模式 */ void enter_sleep_mode() { SCB->SCR &= ~SCB_SCR_SLEEPONEXIT; // 立即进入睡眠 //SCB->SCR |= SCB_SCR_SLEEPONEXIT; // 所有中断程序处理完后再进入睡眠 __wfi(); } int main(void) { USART_Init(); LED_Init(); LED_On(LED_BLUE); printf("测试STM32芯片进入低功耗 - 睡眠模式 \n"); printf("5s后STM32芯片进入睡眠模式 \n"); SysTick_DelayS(2); printf("3s后STM32芯片进入睡眠模式 \n"); SysTick_DelayS(1); printf("2s后STM32芯片进入睡眠模式 \n"); SysTick_DelayS(1); printf("1s后STM32芯片进入睡眠模式 \n"); SysTick_DelayS(1); // !进入睡眠模式 enter_sleep_mode(); // 蓝灯依然点亮 printf("STM32正常工作 \n"); while(1) { LED_Blink(LED_BLUE); } }

2 停止模式

/** * 需求 : 测试STM32芯片进入低功耗 - 停止模式 */ /** * 停止模式 */ void enter_stop_mode() { // 开启时钟 RCC->APB1ENR |= RCC_APB1ENR_PWREN; // 深睡眠 SCB->SCR |= SCB_SCR_SLEEPDEEP; // 掉电 PWR->CR &= ~PWR_CR_PDDS; // 低功耗 PWR->CR |= PWR_CR_LPDS; __wfi(); } /** * 睡眠模式 */ void enter_sleep_mode() { // 浅睡眠 SCB->SCR &= ~SCB_SCR_SLEEPDEEP; SCB->SCR &= ~SCB_SCR_SLEEPONEXIT; // 立即进入睡眠 //SCB->SCR |= SCB_SCR_SLEEPONEXIT; // 所有中断程序处理完后再进入睡眠 __wfi(); } void system_clock_reset(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* Enable HSE */ RCC->CR |= ((uint32_t)RCC_CR_HSEON); do { HSEStatus = RCC->CR & RCC_CR_HSERDY; StartUpCounter++; } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); /* Enable PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) { } /* Select PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; /* Wait till PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { } } int main(void) { USART_Init(); KEY_Init(); LED_Init(); LED_On(LED_BLUE); printf("测试STM32芯片进入低功耗 - 停止模式 \n"); printf("5s后STM32芯片进入停止模式 \n"); SysTick_DelayS(2); printf("3s后STM32芯片进入停止模式 \n"); SysTick_DelayS(1); printf("2s后STM32芯片进入停止模式 \n"); SysTick_DelayS(1); printf("1s后STM32芯片进入停止模式 \n"); SysTick_DelayS(1); // !进入停止模式 enter_stop_mode(); // !外部中断唤醒芯片后,默认会采用HSI的震荡电路的频率,所以不是72M。 // !所以如果想要STM32芯片正常工作,那么就需要重新选择PLL时钟源 system_clock_reset(); SysTick_DelayMs(10); // 蓝灯依然点亮 printf("STM32正常工作 \n"); while(1) { LED_Blink(LED_BLUE); } }

3 待机模式

/** * 需求 : 测试STM32芯片进入低功耗 - 待机模式 */ /** * 待机模式 */ void enter_standby_mode() { // 开启时钟 RCC->APB1ENR |= RCC_APB1ENR_PWREN; // 深睡眠 SCB->SCR |= SCB_SCR_SLEEPDEEP; // 掉电 PWR->CR |= PWR_CR_PDDS; // 清除唤醒标志位 PWR->CR |= PWR_CR_CWUF; // 使能唤醒引脚 PWR->CSR |= PWR_CSR_EWUP; __wfi(); } /** * 停止模式 */ void enter_stop_mode() { // 开启时钟 RCC->APB1ENR |= RCC_APB1ENR_PWREN; // 深睡眠 SCB->SCR |= SCB_SCR_SLEEPDEEP; // 掉电 PWR->CR &= ~PWR_CR_PDDS; // 低功耗 PWR->CR |= PWR_CR_LPDS; __wfi(); } /** * 睡眠模式 */ void enter_sleep_mode() { // 浅睡眠 SCB->SCR &= ~SCB_SCR_SLEEPDEEP; SCB->SCR &= ~SCB_SCR_SLEEPONEXIT; // 立即进入睡眠 //SCB->SCR |= SCB_SCR_SLEEPONEXIT; // 所有中断程序处理完后再进入睡眠 __wfi(); } void system_clock_reset(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* Enable HSE */ RCC->CR |= ((uint32_t)RCC_CR_HSEON); do { HSEStatus = RCC->CR & RCC_CR_HSERDY; StartUpCounter++; } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); /* Enable PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) { } /* Select PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; /* Wait till PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { } } int main(void) { USART_Init(); KEY_Init(); LED_Init(); LED_On(LED_BLUE); printf("测试STM32芯片进入低功耗 - 待机模式 \n"); printf("5s后STM32芯片进入待机模式 \n"); SysTick_DelayS(2); printf("3s后STM32芯片进入待机模式 \n"); SysTick_DelayS(1); printf("2s后STM32芯片进入待机模式 \n"); SysTick_DelayS(1); printf("1s后STM32芯片进入待机模式 \n"); SysTick_DelayS(1); // !进入待机模式 enter_standby_mode(); while(1) { } }

三、寄存器介绍

四、归纳和总结

相同点

  1. 三种模式均通过PWR外设控制,核心操作是配置PWR_CR寄存器 + 执行WFI/WFE指令。
  2. 唤醒后都需要重新配置部分硬件(待机模式需完全重启,停止模式需配置外设时钟,睡眠模式无需额外配置)。
  3. 低功耗的核心逻辑都是减少时钟和电压调节器的功耗消耗

不同点

  1. 断电程度:睡眠模式 < 停止模式 < 待机模式,断电越彻底,功耗越低,但数据保持能力越弱。
  2. 唤醒难度:睡眠模式最容易(任意中断 / 事件),待机模式最难(仅特定唤醒源)。
  3. 恢复速度:睡眠模式最快(无缝恢复),待机模式最慢(相当于复位重启)。

核心参数对比

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 20:38:41

【AI开发宝典】字节跳动Agent实践手册:从0到1构建你的智能助手,大模型应用不再难!

《字节跳动 Agent 实践手册》系统构建了 Agent 技术从理论到实践、从技术到业务的完整指导体系&#xff0c;全面覆盖字节跳动 Agent 技术应用的核心维度。 手册开篇明确 Agent 作为具备自主性与社会性的软件实体&#xff0c;深度融入办公、电商、内容创作、教育等多元业务线&a…

作者头像 李华
网站建设 2026/4/17 9:32:55

海外盲盒小程序开发,加快企业盲盒出海收益[特殊字符]

海外盲盒小程序开发&#xff0c;加快企业盲盒出海收益&#x1f4b0;海外盲盒小程序应具备哪些功能❓1、语言系统&#xff1a;在小程序平台上&#xff0c;支持多种语言切换&#xff0c;满足不同地区的消费者需求。2、盲盒商城&#xff1a;用户在首页可以清晰看到各类盲盒商品&am…

作者头像 李华
网站建设 2026/4/5 7:57:50

基于AD9361的BPSK调制解调器探索:位同步与误码率测试

基于AD9361的BPSK调制解调器、位同步、误码率测试demo。 零中频架构&#xff0c;适用于AD9361等软件无线电平台&#xff0c;带AD9361纯逻辑FPGA驱动&#xff0c;verilog代码&#xff0c;Vivado 2019.1工程。 本产品为代码最近在捣鼓软件无线电相关的项目&#xff0c;基于AD9361…

作者头像 李华
网站建设 2026/4/11 11:10:47

探索 Comsol 中的石墨烯吸收器:基于 Kubo 模型的奇妙之旅

comsol石墨烯吸收器&#xff0c;Kubo模型。 编号031在电磁学与材料科学的交叉领域&#xff0c;石墨烯吸收器一直是研究热点。而 Comsol 作为强大的多物理场仿真软件&#xff0c;为我们深入探究石墨烯吸收器的特性提供了绝佳平台&#xff0c;其中 Kubo 模型更是理解石墨烯光学响…

作者头像 李华
网站建设 2026/4/16 21:23:23

Python与自动化测试:提高软件质量和稳定性

在软件开发过程中&#xff0c;自动化测试是提高软件质量和稳定性的重要手段之一。Python作为一种简洁而强大的编程语言&#xff0c;为自动化测试提供了丰富的工具和库。本文将介绍几个常见的自动化测试案例&#xff0c;并提供详细的Python代码示例&#xff0c;帮助您更好地理解…

作者头像 李华
网站建设 2026/4/11 6:18:29

3年测试经验,测试用例应该达到这个水平才合格

状态迁移法主要关注在测试状态转移的正确性上面。对于一个有限状态机&#xff0c;通过测试验证其在给定的条件内是否能够产生需要的状态变化&#xff0c;有没有不可达的状态和非法的状态&#xff0c;是否可能产生非法的状态转移等。通过构造能导致状态迁移的事件&#xff0c;来…

作者头像 李华