STM32F10x进入低功耗模式

STM32F10x进入低功耗模式

目录

  • STM32F10x进入低功耗模式
    • 1 低功耗模式简介
    • 2 睡眠模式详解
    • 3 停止模式详解
    • 4 待机模式详解
    • 5 示例代码
      • 5.1 标准库函数定义
      • 5.2 进入低功耗模式参考代码
    • 结束语

1 低功耗模式简介

在系统或电源复位以后,微控制器处于运行状态。当CPU不需继续运行时,可以利用多种低功耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。

STM32F10x有三种低功耗模式:
1、睡眠模式
Cortex-M3内核停止,所有外设包括Cortex™-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行
2、停止模式
所有的时钟都已停止
3、待机模式
1.8V电源关闭(CPU核心区域)

低功耗模式一览:
在这里插入图片描述
STM32电源框图:
在这里插入图片描述

此外,在运行模式下,可以通过以下方式中的一种降低功耗:
1、降低系统时钟。
2、关闭APB和AHB总线上未被使用的外设时钟。

2 睡眠模式详解

通过执行WFI或WFE指令可以进入睡眠状态。根据Cortex™-M3系统控制寄存器中的SLEEPONEXIT位的值,有两种选项可用于选择睡眠模式进入机制:
1、SLEEP-NOW:如果SLEEPONEXIT位被清除,当WFI或WFE被执行时,微控制器立即进入睡眠模式。
2、SLEEP-ON_EXIT:如果SLEEPONEXIT位被置位,系统从最低优先级的中断处理程序中退出时,微控制器就立即进入睡眠模式。

SLEEP-NOW模式一览:
在这里插入图片描述
SLEEP-ON_EXIT模式一览:
在这里插入图片描述

3 停止模式详解

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

停止模式进入和退出的方法如下:
在这里插入图片描述
进入停止模式:
在停止模式下,通过设置电源控制寄存器(PWR_CR)的LPDS位使内部调节器进入低功耗模式,能够降低更多的功耗。
需要注意:
1、如果正在进行闪存编程,直到对内存访问完成,系统才进入停止模式。
2、如果正在进行对APB的访问,直到对APB访问完成,系统才进入停止模式。
3、在进入停止模式前,如果一些外设没有被关闭,那么外设仍然消耗电流,如串口、ADC、DAC等。

退出停止模式:
通过中断或者唤醒事件可以退出停止模式。
需要注意:
1、退出停止模式后,HSI RC振荡器被默认选为系统时钟。
2、当电压调节器处于低功耗模式下,当系统从停止模式退出时,将会有一段额外的启动延时。如果在停止模式期间保持内部调节器开启,则退出启动时间会缩短,但相应的功耗会增加。

4 待机模式详解

待机模式可实现系统的最低功耗。该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个1.8V供电区域被断电。PLL、HSI和HSE振荡器也被断电。SRAM和寄存器内容丢失。只有备份的寄存器和待机电路维持供电。

待机模式进入和退出的方法如下:
在这里插入图片描述

进入待机模式:
进入待机模式需要做到以下几点:
1、设置Cortex-M3系统控制寄存器中的SLEEPDEEP位。
2、清除电源控制寄存器(PWR_CR)中的PDDS位。
3、通过设置PWR_CR中LPDS位选择电压调节器的模式。

退出待机模式:
当一个外部复位(NRST引脚)、IWDG复位、WKUP引脚上的上升沿或RTC闹钟事件的上升沿发生时,微控制器从待机模式退出。从待机唤醒后,除了电源控制/状态寄存器(PWR_CSR),所有寄存器被复位。
从待机模式唤醒后的代码执行等同于复位后的执行(采样启动模式引脚、读取复位向量等)。电源控制/状态寄存器(PWR_CSR)将会指示内核由待机状态退出。

5 示例代码

5.1 标准库函数定义

睡眠模式标准库函数代码:

static __INLINE  void __WFI()                     { __ASM ("wfi"); }
static __INLINE  void __WFE()                     { __ASM ("wfe"); }

停机模式标准库函数代码:

/*** @brief  Enters STOP mode.* @param  PWR_Regulator: specifies the regulator state in STOP mode.*   This parameter can be one of the following values:*     @arg PWR_Regulator_ON: STOP mode with regulator ON*     @arg PWR_Regulator_LowPower: STOP mode with regulator in low power mode* @param  PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction.*   This parameter can be one of the following values:*     @arg PWR_STOPEntry_WFI: enter STOP mode with WFI instruction*     @arg PWR_STOPEntry_WFE: enter STOP mode with WFE instruction* @retval None*/
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{uint32_t tmpreg = 0;/* Check the parameters */assert_param(IS_PWR_REGULATOR(PWR_Regulator));assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));/* Select the regulator state in STOP mode ---------------------------------*/tmpreg = PWR->CR;/* Clear PDDS and LPDS bits */tmpreg &= CR_DS_MASK;/* Set LPDS bit according to PWR_Regulator value */tmpreg |= PWR_Regulator;/* Store the new value */PWR->CR = tmpreg;/* Set SLEEPDEEP bit of Cortex System Control Register */SCB->SCR |= SCB_SCR_SLEEPDEEP;/* Select STOP mode entry --------------------------------------------------*/if(PWR_STOPEntry == PWR_STOPEntry_WFI){   /* Request Wait For Interrupt */__WFI();}else{/* Request Wait For Event */__WFE();}/* Reset SLEEPDEEP bit of Cortex System Control Register */SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);  
}

待机模式标准库函数代码:

/*** @brief  Enters STANDBY mode.* @param  None* @retval None*/
void PWR_EnterSTANDBYMode(void)
{/* Clear Wake-up flag */PWR->CR |= PWR_CR_CWUF;/* Select STANDBY mode */PWR->CR |= PWR_CR_PDDS;/* Set SLEEPDEEP bit of Cortex System Control Register */SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM   )__force_stores();
#endif/* Request Wait For Interrupt */__WFI();
}

5.2 进入低功耗模式参考代码

低功耗模式参考代码:

#include "delay.h"
#include "sys.h"
#include "usart.h"#define KEY0    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)  //读取按键0         
#define KEY1    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)  //读取按键1
#define KEY2    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)  //读取按键2 
#define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)  //读取按键3(WK_UP) uint8_t set_mcu_mode = 0;   //设置MCU模式,0:运行状态,1:睡眠模式,2:停机模式,3:待机模式//外部中断0服务程序
void EXTI0_IRQHandler(void)
{delay_ms(10);//消抖if(WK_UP == 1)	   //WK_UP按键{				 SystemInit();	 //MCU被唤醒,重新配置系统时钟set_mcu_mode = 0;printf("MCU wake up\r\n");}EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位  
}//外部中断2服务程序
void EXTI2_IRQHandler(void)
{delay_ms(10);//消抖if(KEY2 == 0)	  //按键KEY2{set_mcu_mode = 1; //需要进入睡眠模式printf("key2\r\n");}		 EXTI_ClearITPendingBit(EXTI_Line2);  //清除LINE2上的中断标志位  
}
//外部中断3服务程序
void EXTI3_IRQHandler(void)
{delay_ms(10);//消抖if(KEY1 == 0)	 //按键KEY1{				 set_mcu_mode = 2; //需要进入停机模式printf("key1\r\n");}		 EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位  
}void EXTI4_IRQHandler(void)
{delay_ms(10);//消抖if(KEY0 == 0)	 //按键KEY0{set_mcu_mode = 3; //需要进入待机模式printf("key0\r\n");}		 EXTI_ClearITPendingBit(EXTI_Line4);  //清除LINE4上的中断标志位  
}//外部中断初始化
void EXTIX_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOE, ENABLE);//使能PORTA,PORTE时钟GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0-KEY2GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,E3,E4GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;//WK_UP KEY-->GPIOA0GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉	  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA0RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能复用功能时钟//GPIOE2 中断线以及中断初始化配置 下降沿触发GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);EXTI_InitStructure.EXTI_Line=EXTI_Line2; //KEY2EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);	 	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器//GPIOE3 中断线以及中断初始化配置 下降沿触发 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);EXTI_InitStructure.EXTI_Line=EXTI_Line3;  //KEY1EXTI_Init(&EXTI_InitStructure);	  	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器//GPIOE4 中断线以及中断初始化配置 下降沿触发	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);EXTI_InitStructure.EXTI_Line=EXTI_Line4; //KEY0EXTI_Init(&EXTI_InitStructure);	  	//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器//GPIOA0 中断线以及中断初始化配置 上升沿触发 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); EXTI_InitStructure.EXTI_Line=EXTI_Line0; //WK_UP KEYEXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_Init(&EXTI_InitStructure);		//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;				//使能按键WK_UP所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;			//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能外部中断通道NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;				//使能按键KEY2所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;			//子优先级2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能外部中断通道NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;				//使能按键KEY1所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;			//子优先级1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能外部中断通道NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器  	  NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;				//使能按键KEY0所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;			//子优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能外部中断通道NVIC_Init(&NVIC_InitStructure);  	  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}void LED_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PB,PE端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //LED0-->PB5 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHzGPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB5GPIO_SetBits(GPIOB,GPIO_Pin_5);						 	 //PB5 输出高
}int main(void)
{		delay_init();	    	//延时函数初始化	  uart_init(115200);	    //串口初始化为115200LED_Init();		  		//初始化与LED连接的硬件接口EXTIX_Init();		 	//外部中断初始化while(1){	    	if(set_mcu_mode > 0){switch (set_mcu_mode){case 1://进入睡眠模式printf("Enter sleep mode\r\n");__WFI();break;case 2://进入停机模式printf("Enter stop mode\r\n");PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);break;case 3://进入待机模式printf("Enter standby mode\r\n");PWR_EnterSTANDBYMode();break;default:break;}}GPIO_ResetBits(GPIOB, GPIO_Pin_5);	//点亮LED0delay_ms(200);	  GPIO_SetBits(GPIOB, GPIO_Pin_5);	//关闭LED0delay_ms(200);	}
}

示例代码测试结果:

1、MCU正常运行,LED0定时闪烁。
2、按下KEY0,MCU进入待机模式,LED0熄灭,再按下KEY3(WK_UP),MCU被唤醒继续运行。
3、按下KEY1,MCU进入停机模式,LED0熄灭,再按下KEY3(WK_UP),MCU被唤醒继续运行。
4、按下KEY2,MCU进入睡眠模式,LED0熄灭,再按下KEY3(WK_UP),MCU被唤醒继续运行。

结束语

上面的测试例子只是给大家做一个参考,实际上需要根据项目的具体需求去补充很多细节,比如进入低功耗模式的触发条件,唤醒的方式,以及进入睡眠之前对外设的处理,等等,这样才能保证在实现功能需求的同时,又能尽可能的把功耗降到最低。
好了,关于STM32如何进入低功耗模式就介绍到这里,如果你们有什么问题,欢迎评论区留言。

如果这篇文章能够帮到你,就…懂的。
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/213493.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Spring】 IoCDI

回顾 企业命名规范 大驼峰:BookDao(首字母都大写) 类名 小驼峰:bookDao(第一个字母小写) 方法名 蛇形:book_dao(小写下划线_) 数据库 串形:book-dao(小写连字符-) 项目文件夹 各种注解 学习Spring MVC, 其实就是学习各种Web开发需要⽤的到注解 a. RequestMapping: 路由…

【elementui】el-popover在列表里循环使用,取消的doClose无效解决办法

目录 一、需求效果二、代码详情html方法接口 一、需求效果 在使用elementui的Popover 弹出框时&#xff0c;需求是在table列表里使用&#xff0c;循环出来&#xff0c;无法取消。 二、代码详情 html <el-table-column v-if"checkPermission([admin,user:resetPass…

案例015:Java+SSM+uniapp基于微信小程序的校园防疫系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

人工智能带来的各方面影响

近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术在各个领域中的应用越来越广泛&#xff0c;已经开始对我们的生活方式、社会和经济结构产生深远的影响。 1.人工智能家庭化。人工智能技术使我们的生活变得更加便利和智能化。在家庭日常中&#xff0c;智能家居、智能…

C++学习之路(二)C++如何实现一个超简单的学生信息管理系统?C++示例和小项目实例

这个示例实现了一个简单的学生信息管理系统。它包括了学生类的定义&#xff0c;可以添加学生信息、显示所有学生信息&#xff0c;将学生信息保存到文件并从文件加载信息。通过这个示例&#xff0c;你可以了解到如何使用类、函数和文件操作来构建一个基本的信息管理系统。 一个简…

单片机串口通用收发代码

本篇博客大部分是自己收集和整理&#xff0c;借鉴了很多大佬的图片和知识点整理&#xff0c;如有侵权请联系我删除。本博客内容原创&#xff0c;创作不易&#xff0c;转载请注明 串口接收最后应有一定的协议&#xff0c;如发送一帧数据应该有头标志或尾标志&#xff0c;也可两个…

使用Pytorch从零开始构建GRU

门控循环单元 (GRU) 是 LSTM 的更新版本。让我们揭开这个网络的面纱并探索这两个兄弟姐妹之间的差异。 您听说过 GRU 吗&#xff1f;门控循环单元&#xff08;GRU&#xff09;是更流行的长短期记忆&#xff08;LSTM&#xff09;网络的弟弟&#xff0c;也是循环神经网络&#x…

【开源】基于Vue.js的用户画像活动推荐系统

项目编号&#xff1a; S 061 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S061&#xff0c;文末获取源码。} 项目编号&#xff1a;S061&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 兴趣标签模块2.3 活…

练习七-在Verilog中使用任务task

在Verilog中使用任务task 1&#xff0c;任务目的2&#xff0c;RTL代码&#xff0c;交换3&#xff0c;测试代码4&#xff0c;波形显示 1&#xff0c;任务目的 &#xff08;1&#xff09;掌握任务在verilog模块设计中的应用&#xff1b; &#xff08;2&#xff09;学会在电平敏感…

今日祝福语道一声早安,惟愿你时时安好,天天幸福!

1、托太阳公公轻轻的叩醒你沉睡的心灵&#xff0c;将暖暖的阳光洒满你全身&#xff0c;愿你精神抖擞信心百倍的迎接新的一天&#xff0c;朋友&#xff0c;早安&#xff01; 2、一天中&#xff0c;第一个叫醒你的是闹钟&#xff0c;第一眼看到的是阳光&#xff0c;第一件要做的事…

目标检测框存在内嵌情况分析与解决

这里写目录标题 问题描述原因分析与解决方法&#xff1a;后续及思考参考文档 问题描述 目标检测模型输出的检测框存在内嵌情况。 原因分析与解决方法&#xff1a; 根据经验&#xff0c;第一感觉是后处理nms部分出了问题。来看下对应的代码&#xff1a; static float CalcIou…

牛客 HJ106 字符逆序 golang实现

牛客题目算法连接 题目 golang 实现 package mainimport ("fmt""bufio""os" )func main() {str, _ : bufio.NewReader(os.Stdin).ReadString(\n)if len(str) 0 {return } else {newstr:""strLen:len(str)-1for i:strLen;i>0;i-…