news 2026/5/1 10:56:20

电源控制--低功耗(睡眠、停机、待机)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
电源控制--低功耗(睡眠、停机、待机)

一、电源框图

STM32的工作电压(VDD)是2.0~3.6V,内置电压1.8V;

1.内容补充

(1)电压调节器三种工作模式(复位后):

I.运转模式:调节器以正常功耗提供1.8V电源(内核、内存和外设都正常使用)

II. 停止模式:调节器以低功耗模式提供1.8V电源(CPU不运行,但数据还在),用于保存寄存器和SRAM的内容

III.调节器停止供电,除了备用电路和备份域外(若没有备用电池这些区域内容也会丢失),寄存器和SRAE的内容全部丢失。

(2)上电复位掉电复位

为了保证底层寄存器的值统一,上电时会对所有寄存器进行复位,所以每个寄存器都有一个复位值。掉电同理;但是复位不是瞬间完成的,是有滞后时间的,来避免抖动现象(毛刺现象;不稳定)

(3)低功耗

用户根据最低电源消耗、最快启动时间和可用的唤醒源等条件选择一个最佳的的低功耗模式,STM32F10xxx有三种低功耗模式:睡眠、停机和待机。

二、三种低功耗模式

1.睡眠模式

(1)进入睡眠模式

通过执行FWI或WFE指令进入睡眠状态,并根据内核系统控制寄存器SCB_SCR中的SLEEPONEXIT位的值选择睡眠进入的机制:

(2)补充知识点

I.在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态。
II.interrupt(中断):是需要手动运行的 ;event(事件):是自动进行的
III.__wfi __WFI 是一样的进入睡眠模式(__wfe和__WFE同理)

VI.退出睡眠状态的条件--任一中断
V.为什么要延迟5s再进入睡眠模式(停机模式、待机模式同理)

为了避免下一次烧录时一上来就睡眠,程序还未烧录完成(代码的烧录需要依靠CPU,此时烧录不进去),可能导致代码未写完成就睡眠后无法再将其唤醒,所以加上5s时希望当它5s内将程序烧录进去;

IV、HAL库中嘀嗒定时器默认是使用中断方式触发的(1ms触发一次)

HAL_SuspendTick(); -->暂停滴答定时器(只是嘀嗒定时器的中断暂停,其他功能仍正常工作)

HAL_ResumeTick(); -->恢复嘀嗒定时器的中断

IIV、要使用USART中断需要单独启用
uint8_t buffer[4] = {0}; HAL_UART_Receive_IT(&huart1,buffer,4);

(3)代码实现

I、寄存器的方式
/** * 睡眠模式 */ void enter_sleep_mode(void) { //浅睡眠 SCB->SCR &= ~SCB_SCR_SLEEPDEEP; 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); } }
II、HAL库的方式
printf("测试STM32进入低功耗 - 睡眠模式 \n"); printf("5s后stm32芯片进入睡眠模式 \n"); HAL_Delay(2000); printf("3s后stm32芯片进入睡眠模式 \n"); HAL_Delay(1000); printf("2s后stm32芯片进入睡眠模式 \n"); HAL_Delay(1000); printf("1s后stm32芯片进入睡眠模式 \n"); HAL_Delay(1000); //开启UART中断 uint8_t buffer[4] = {0}; HAL_UART_Receive_IT(&huart1,buffer,4); //暂停嘀嗒定时器的中断 HAL_SuspendTick(); //! 进入睡眠模式 HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON,PWR_SLEEPENTRY_WFI); //开启嘀嗒定时器的中断 HAL_ResumeTick(); // 蓝灯依然点亮 printf("STM32正常工作 \n");

2.停机模式

停止模式下电压调节器可运行在正常或低功耗模式,此时在1.8V供电区域的的所有时钟都被停止,PLL、HSI和HSE RC振荡器的功能被禁止,SRAM和寄存器内容被保留下来。

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

(1)进入停止模式

(2)补充知识点

I.上下文的概念

II、PWR不属于内核,所以需要开启时钟(供电)
III、上电后STM32的时钟先选择HSI_RC震荡电路(8MHZ)后再转换到HSE+PLL(72MHZ)

刚上电后,为了确定芯片刚上电就能运行,而HSE+PLL(锁相环倍频器)上电后需要一段时间稳定,所以先选择HSI(精度低频率低,在芯片内部上电就能使能无需稳定),后等到HSE的频率稳定后使用HSE+PLL

VI、注意停止模式恢复正常后的时钟为HSI RC所以需要重新设置为HSE+PLL(72MHZ)

(3)代码实现

I、寄存器的方式
/** * 停止模式 */ 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(); }
/** * 重新设置PLL为时钟源 */ void system_clock_reset(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* Enable HSE */ RCC->CR |= ((uint32_t)RCC_CR_HSEON); /* Wait till HSE is ready and if Time out is reached exit */ 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); } }
II、HAL库的方式
printf("测试STM32芯片进入低功耗 - 停止模式 \n"); printf("5s后STM32芯片进入停止模式 \n"); HAL_Delay(2000); printf("3s后STM32芯片进入停止模式 \n"); HAL_Delay(1000); printf("2s后STM32芯片进入停止模式 \n"); HAL_Delay(1000); printf("1s后STM32芯片进入停止模式 \n"); HAL_Delay(1000); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); SystemClock_Config(); HAL_Delay(10); printf("STM32正常工作 \n");

3.待机模式

(1)进入待机模式

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

I、复位引脚(始终有效)。

II、当被设置为防侵入或校准输出时的TAMPER引脚。

III、被使能的唤醒引脚。

(2)补充知识点

I、SBF位和WUF位

SBF = 1 表示之前是待机模式现在被唤醒

WUF = 1 表示是被WKUP唤醒或RTC实时时钟

WUF = 0 则是被复位键唤醒

II、HAL库方式勾选WKUP引脚是代表可以使用此引脚作为唤醒引脚,要使用的话还需要开始WKUP使能

(3)代码实现

I、寄存器的方式
/** * 待机模式 */ 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(); }
int main(void) { USART_Init(); KEY_Init(); LED_Init(); LED_On(LED_BLUE); // 开启时钟 RCC->APB1ENR |= RCC_APB1ENR_PWREN; // !获取芯片待机状态,判断之前是否曾经进入过待机模式 if ((PWR->CSR & PWR_CSR_SBF) != 0) { printf("STM32芯片从待机模式被"); // 复位状态 PWR->CR |= PWR_CR_CSBF; if ((PWR->CSR & PWR_CSR_WUF) == 0) { printf("Reset复位键唤醒 \n"); } else { // 复位状态 PWR->CR |= PWR_CR_CWUF; printf("WKUP唤醒引脚唤醒 \n"); } } 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(); printf("STM32正常工作 \n");
II、HAL库的方式
if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != 0 ){ printf("STM32芯片从待机模式被"); //复位状态 PWR->CR |= PWR_CR_CSBF; __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB); if(__HAL_PWR_GET_FLAG(PWR_FLAG_WU) == 0){ printf("Reset复位键唤醒 \n"); }else{ //复位状态 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); printf("WKUP唤醒引脚唤醒 \n"); } } printf("测试STM32芯片进入低功耗 - 待机模式 \n"); printf("5s后STM32芯片进入待机模式 \n"); HAL_Delay(2000); printf("3s后STM32芯片进入待机模式 \n"); HAL_Delay(1000); printf("2s后STM32芯片进入待机模式 \n"); HAL_Delay(1000); printf("1s后STM32芯片进入待机模式 \n"); HAL_Delay(1000); //!使能WK引脚 HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); // !进入待机模式 HAL_PWR_EnterSTANDBYMode(); printf("STM32正常工作 \n");
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 10:34:04

ConvertToUTF8插件完全指南:彻底解决编码乱码问题

ConvertToUTF8插件完全指南:彻底解决编码乱码问题 【免费下载链接】ConvertToUTF8 A Sublime Text 2 & 3 plugin for editing and saving files encoded in GBK, BIG5, EUC-KR, EUC-JP, Shift_JIS, etc. 项目地址: https://gitcode.com/gh_mirrors/co/Convert…

作者头像 李华
网站建设 2026/5/1 9:13:48

Kotaemon的可解释性设计:为什么这对企业如此重要?

Kotaemon的可解释性设计:为什么这对企业如此重要? 在金融、医疗和法律等高敏感领域,AI系统的一次“自信但错误”的回答,可能带来合规风险、客户信任崩塌甚至法律责任。当一个智能客服声称“根据公司政策,您可以全额报销…

作者头像 李华
网站建设 2026/5/1 8:49:57

模型月更 vs 实时反馈:气象预测 Agent 的持续学习机制,你真的了解吗?

第一章:气象预测 Agent 的模型更新在现代气象预测系统中,Agent 架构被广泛用于实现分布式数据采集与智能决策。随着环境数据的动态变化,定期更新预测模型成为确保准确性的关键环节。模型更新不仅涉及算法迭代,还需保证服务连续性与…

作者头像 李华
网站建设 2026/5/1 9:57:12

机房动环监控是什么?主要包括哪些功能?

机房动环监控是一种全面的管理系统,旨在确保机房的环境和设备运行稳定。主要功能包括温湿度监控、故障报警、视频监控和能源管理等。首先,通过传感器实时捕捉环境数据,温湿度监控功能保证设备在合适的条件下运行,避免由于环境异常…

作者头像 李华
网站建设 2026/5/1 8:54:15

从零搭建智能家联动系统,99%的人都忽略的3个关键细节

第一章:从零构建智能家居Agent的核心理念在物联网快速发展的今天,智能家居Agent不再只是执行预设规则的自动化脚本,而是具备感知、决策与自适应能力的智能实体。其核心理念在于构建一个可扩展、模块化且具备上下文理解能力的系统架构&#xf…

作者头像 李华
网站建设 2026/5/1 3:07:19

医疗影像辅助诊断的5个关键指标,99%的开发者都忽略了

第一章:医疗影像Agent辅助诊断的演进与现状近年来,随着人工智能技术的飞速发展,医疗影像Agent在辅助诊断领域取得了显著进展。这些智能系统通过深度学习算法分析X光、CT、MRI等医学图像,帮助医生更快速、准确地识别病灶&#xff0…

作者头像 李华