细说STM32F407单片机电源低功耗SleepMode模式及应用示例

目录

一、STM32F4的低功耗模式

1、睡眠(Sleep)模式

2、停止(Stop)模式

3、待机(Standby)模式

二、睡眠模式

1、进入睡眠模式

2、睡眠模式的状态

3、退出睡眠模式

4、SysTick的影响

三、应用示例

1、工程配置

(1) 时钟、DEBUG、GPIO、CodeGenerator

(2) USART6

(3) NVIC

2、软件设计

(1) main.h

(2)main.c

四、下载并调试


        电池供电的嵌入式系统一般非常注意功耗控制,尽量使系统的功耗最低。STM32F4系列MCU提供了多种运行模式,CubeMX也提供了功耗分析的功能。本文介绍STM32F4的SleepMode功耗模式,以及如何通过该功耗模式的控制实现系统的低功耗。

一、STM32F4的低功耗模式

        系统复位后,MCU处于正常运行模式。在正常运行模式下,CPU由HCLK时钟信号驱动连续执行程序指令。用户可以采取一些措施降低系统正常运行时的功耗,例如,可以降低HCLK时钟频率,或者将不使用的外设的时钟信号关闭。

        从main()函数的代码可以看出,在执行完各种初始化后,最后都是执行一个while()死循环。在while()循环里,通过轮询方式处理各种事务,或通过中断响应处理各种事务。在正常运行模式下,while()循环里的程序代码是一直执行的,即使一行代码都没有。所以在正常运行模式下,一般的嵌入式系统的CPU计算时间都是浪费的。

        除了正常运行模式,STM32F4系列MCU还有3种低功耗模式

1、睡眠(Sleep)模式

        Cortex-M4内核时钟停止,1.2V调压器正常工作,外设保持运行。通过WFI(wait for interrupt)或WFE(wait for event)指令进入睡眠模式。进入睡眠模式后,CPU不再执行新的代码。CPU可以被中断或事件唤醒,唤醒后继续执行进入睡眠点之后的代码。

2、停止(Stop)模式

        1.2V域所有时钟都停止,所有外设停止工作,内部调压器可以处于运行或低功耗模式,内部SRAM和寄存器的内容被保留,HSI和HSE振荡器关闭。通过EXTI中断或EXTI事件唤醒,CPU从停止处继续执行代码。

3、待机(Standby)模式

        调压器停止,1.2V域断电,内部SRAM和寄存器的内容丢失。只能通过SYS_WKUP引脚的上升沿、RTC闹钟事件、RTC唤醒事件、RTC入侵事件、NRST引脚外部复位等唤醒。从待机模式唤醒相当于系统复位,程序从头开始执行。

        在这3种低功耗模式中,待机模式功耗最低,但是从待机模式唤醒相当于系统复位,程序从头开始执行。睡眠模式和停止模式都能停止CPU的程序执行,被唤醒后,从程序停止处继续执行。应根据系统的实际功能需求选择合适的低功耗模式。

二、睡眠模式

1、进入睡眠模式

        通过执行Cortex-M4内核的WFI(Wait For Interrupt)指令或WFE(Wait For Event)指令可以进入睡眠模式。根据Cortex-M4F系统控制寄存器(System Control Register,SCR)的SLEEPONEXIT位的设置,有两种进入睡眠模式的方式

  • 立即睡眠:如果SLEEPONEXIT位是0,MCU在执行WFI指令或WFE指令时,立即进入睡眠模式。
  • 退出时睡眠:如果SLEEPONEXIT位是1,MCU在退出优先级最低的中断ISR后,立即进入睡眠模式。

        在进入睡眠模式之前,可以调用HAL的驱动函数设置SLEEPONEXIT的值,这两个函数原型如下:

void HAL_PWR_EnableSleepOnExit(void)	//将SLEEPONEXIT位置1
void HAL_PWR_DisableSleepOnExit(void)	//将SLEEPONEXIT位清零

        进入睡眠模式的HAL函数是HAL_PWR_EnterSLEEPMode(),其源代码如下:

void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(Regulator);

  /* Check the parameters */
  assert_param(IS_PWR_REGULATOR(Regulator));
  assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry));

  /* Clear SLEEPDEEP bit of Cortex System Control Register */
  CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));

  /* Select SLEEP mode entry -------------------------------------------------*/
  if(SLEEPEntry == PWR_SLEEPENTRY_WFI)
  {   
    /* Request Wait For Interrupt */
    __WFI();
  }
  else
  {
    if(SLEEPEntry != PWR_SLEEPENTRY_WFE_NO_EVT_CLEAR)
    {
      /* Clear all pending event */
      __SEV();
      __WFE();
    }

    /* Request Wait For Event */
    __WFE();
  }
}

         其中,参数Regulator表示调压器在睡眠模式下的状态。其取值使用如下宏定义常量。

PWR_MAINREGULATOR_ON,调压器正常运行。
PWR_LOWPOWERREGULATOR_ON,调压器处于低功耗模式。

        但是参数Regulator的取值在这个函数中并没有意义,因为STM32F4系列MCU在睡眠模式下,调压器总是处于运行状态,而不能是低功耗状态。这个参数是为了与低功耗系列的STM32F MCU的驱动函数相兼容。

        参数SLEEPEntry表示以何种指令进入睡眠模式,WFI指令或WFE指令。其取值使用如下宏定义常量。

PWR_SLEEPENTRY_WFI,使用WFI指令进入睡眠模式。
PWR_SLEEPENTRY_WFE,使用WFE指令进入睡眠模式。

        函数HAL_PWR_EnterSLEEPMode()内部会首先将系统控制寄存器SCR的SLEEPDEEP位清零,这个位如果置1就是深度睡眠模式,在进入停止模式时才将SLEEPDEEP位置1。

2、睡眠模式的状态

        进入睡眠模式后,系统的状态如下:

  • CPU的时钟关闭,CPU停止运行,也就是程序暂停。
  • 所有外设的时钟不停止,外设正常运行,所有I/O引脚的状态与运行时相同。
  • 调压器正常运行。

3、退出睡眠模式

        如果使用WFI指令进入睡眠模式,则NVIC确认的任何外设中断都可以将MCU唤醒。由中断唤醒后,先执行中断的ISR,然后执行WFI指令后面的程序。

        如果使用WFE指令进入睡眠模式,MCU将在有事件发生时立即退出睡眠模式,并执行WFE后的程序。唤醒事件可以通过以下方式产生。

  • 在外设的控制寄存器中使能一个中断事件,但是不在NVIC中使能其全局中断,同时使能系统控制寄存器SCR中的SEVONPEND(Send Event on Pending bit)位。当MCU从WFE恢复时,需要清除相应外设的事件中断标志位和外设NVIC中断挂起位。
  • 配置一个外部或内部EXTI线为事件模式。当CPU从WFE中恢复时,因为对应事件线的挂起位没有被置位,不必清除相应外设的中断标志位或NVIC中断通道挂起位。HAL库中有两个函数用于设置系统控制寄存器SCR中的SEVONPEND位的值。
void HAL_PWR_EnableSEVOnPend(void)	//SEVONPEND位置1
void HAL_PWR_DisableSEVOnPend(void)	//SEVONPEND位清零

        从睡眠模式唤醒的响应没有任何延迟,是3种低功耗模式中唤醒响应最快的。

4、SysTick的影响

        由于睡眠模式可以由任意中断或事件唤醒,而MCU在HAL初始化时就开启了Cortex-M内核的SysTick定时器,这个定时器每隔1ms中断一次。如果MCU处于睡眠状态,SysTick定时器的中断会将MCU从睡眠模式唤醒。

        如果要使睡眠模式不受SysTick中断的影响,需要在进入睡眠状态之前停止SysTick定时器,从睡眠状态恢复后又立即开启SysTick定时器,因为延时函数HAL_Delay()需要用到SysTick定时器。文件stmf4xx_hal.h定义了两个控制SysTick定时器的函数,两个函数原型定义如下:

void HAL_SuspendTick(void);	//暂停SysTick定时器的运行
void HAL_ResumeTick(void);	//恢复SysTick定时器的运行

三、应用示例

本文将创建一个示例项目,测试系统的睡眠模式。继续使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。示例功能和操作流程如下。

  • 将连接KeyRight键的PF6引脚配置为外部中断EXTI6。
  • 在主程序的while循环里,使系统进入睡眠状态后,按下KeyRight键把系统从睡眠状态唤醒。

        本示例要用到USART6、LED1(PA6)和KeyRight键,但是需要将连接KeyRight键的PF6引脚重新设置为外部中断线EXTI6,并设置上拉和下跳沿触发中断。本示例中KeyRight和LED1的引脚GPIO设置结果如图所示。用户还需要在NVIC中开启EXTI6的中断。

        本文引用KEYLED文件夹里的文件,其使用方法和管脚配置请看参考文章。

        参考文章:细说STM32F407单片机以DMA方式读写外部SRAM的方法_片外sram访问熟读-CSDN博客  细说STM32F407单片机以DMA方式读写外部SRAM的方法_片外sram访问熟读-CSDN博客

1、工程配置

(1) 时钟、DEBUG、GPIO、CodeGenerator

        外部时钟,25MHz,设置到HCLK=168MHz,PCLK1=42MHz,PCLK2=84MHz,其它,都设置成168MHz。

        DEBUG,选择serial wire,CodeGenerator的设置同参考文章。

 

(2) USART6

        使用管脚PG9、PG14,默认其它参数。

(3) NVIC

2、软件设计

(1) main.h

        即使PF6管脚被定义多重功能, IDE也自动生成如下驱动。

/* Private defines -----------------------------------------------------------*/
#define KeyRight_Pin GPIO_PIN_6
#define KeyRight_GPIO_Port GPIOF
#define KeyRight_EXTI_IRQn EXTI9_5_IRQn
#define LED1_Pin GPIO_PIN_6
#define LED1_GPIO_Port GPIOA

(2)main.c

/* USER CODE BEGIN 2 */
  printf("Demo22_1_SleepMode:Test Sleep Mode.\r\n\r\n");
  LED1_ON();
  HAL_Delay(1000);	//系统复位后,LED1 1秒后进入睡眠状态
  /* USER CODE END 2 */
  /* USER CODE BEGIN 3 */
	printf("Press KeyRight[S5] to wake up.\r\n");
	printf("After entering SleepMode,");
	printf("the LED1 flashes until the MCU wakes up.\r\n\r\n");
	LED1_OFF();
	HAL_SuspendTick();	//使SysTick定时器暂停

	/* 进入睡眠状态,对于正常的中断,WFI和WFE两种参数都可以唤醒,因为中断肯定是事件 */
	HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);

	/* 按键的EXTI中断唤醒后执行下面的代码 */
	HAL_ResumeTick();	//恢复SysTick定时器
	printf("Resumed from SleepMode.\r\n\r\n");
	for(uint8_t i=0; i<9;i++)	//使LED1 闪烁,延时也可消除按键抖动影响
	{
	  	LED1_Toggle();
	  	HAL_Delay(500);
	}
  }
  /* USER CODE END 3 */

        本示没有为外部中断EXTI6编写回调函数代码,所有用户代码都在main()函数里。

        在while循环里,在使系统进入睡眠状态之前先熄灭LED1,调用函数HAL_SuspendTick()使SysTick定时器暂停,然后调用HAL_PWR_EnterSLEEPMode()函数,用WFI指令进入睡眠模式。在进入睡眠模式后,CPU时钟停止,程序就暂停了。

        在用户按下KeyRight[S5]键时产生EXTI中断,系统被唤醒,继续执行后面的代码。程序先调用函数HAL_ResumeTick()恢复SysTick定时器的运行,因为后面的代码里需要使用HAL_Delay()函数,要用到SysTick定时器。

        本示例在执行函数HAL_PWR_EnterSLEEPMode()进入睡眠模式时,使用WFI方式或WFE方式的效果是一样的,因为中断必然是事件引起的,而事件不一定产生中断

/* USER CODE BEGIN 4 */
// 唤醒SleepMode也可以在这里通过调用回调函数实现

int __io_putchar(int ch)
{
	HAL_UART_Transmit(&huart6,(uint8_t*)&ch,1,0xFFFF);
	return ch;
}
/* USER CODE END 4 */

四、下载并调试

        运行时可以看到示例程序是按期望运行的。系统提示进入睡眠模式后,按KeyRight键可唤醒系统,唤醒后显示提示信息,并且使LED1闪烁几次,然后又进入睡眠状态。要唤醒系统,需要再按KeyRight键。

        如果将程序中调用函数HAL_SuspendTick()的那行语句注释掉,也就是不暂停SysTick定时器,会发现运行时LED1一直闪烁。这是因为在进入睡眠状态后,SysTick定时器中断就将系统唤醒了,而SysTick定时器中断的触发周期是1ms,所以系统睡眠不超过1ms就被唤醒了。在这个程序中,while循环里的代码不会被CPU一直高速循环执行,进入睡眠模式会使CPU暂停执行程序,被唤醒后才继续执行睡眠点之后的代码。本示例为了演示的需要,在系统被唤醒后,用for循环执行了约4000ms的程序(也起到消除按键抖动影响的作用)。在实际的系统中,程序可能大部分时间处于睡眠状态,执行程序的时间可能很短,例如,睡眠1000ms,执行程序才1ms,这样可以大大降低系统的功耗。

        在CubeMX中,为本项目进行功耗计算,只设置了RUN和SLEEP两种步骤,步骤设置中只开启系统实际用到的外设。运行模式下的耗电流是47.18mA,而睡眠模式下的电流是13.18mA。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv11改进,YOLOv11检测头融合RepConv卷积,并添加小目标检测层(四头检测),适合目标检测、分割等任务

摘要 作者提出了一种简单而强大的卷积神经网络架构,其推理阶段采用与 VGG 类似的网络体结构,仅由一堆 3x3 卷积和 ReLU 组成,而训练阶段的模型具有多分支拓扑。这种训练阶段和推理阶段架构的解耦通过结构重参数化技术实现,因此我们将该模型命名为 RepVGG。 # 理论介绍 Re…

ScratchLLMStepByStep:训练自己的Tokenizer

1. 引言 分词器是每个大语言模型必不可少的组件&#xff0c;但每个大语言模型的分词器几乎都不相同。如果要训练自己的分词器&#xff0c;可以使用huggingface的tokenizers框架&#xff0c;tokenizers包含以下主要组件&#xff1a; Tokenizer: 分词器的核心组件&#xff0c;定…

Linux 操作二:文件映射与文件状态

Linux 操作二&#xff1a;文件映射与文件状态查询 文件映射 ​ mmap是一种内存映射文件的方法&#xff0c;即将一个文件或者其它对象映射到进程的地址空间&#xff0c;实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后&#xff0c;进程…

网络编程-TCP套接字

文章目录 初始TCP套接字TCP的Socket APISocketServerSocket 使用TCP模拟通信服务器端客户端 上述测试代码的问题分析IO的输入缓冲区的问题关于TCP协议中的粘包的问题不能进行多线程通信的问题 处理问题之后的完整代码启动多个实例完整代码测试结果 关于IO多路复用机制的引入 初…

flutter开发-figma交互设计图可以转换为flutter源代码-如何将设计图转换为flutter源代码-优雅草央千澈

flutter开发-figma交互设计图可以转换为flutter源代码-如何将设计图转换为flutter源代码-优雅草央千澈 开发背景 可能大家听过过蓝湖可以转ui设计图为vue.js&#xff0c;react native代码&#xff0c;那么请问听说过将figma的设计图转换为flutter源代码吗?本文优雅草央千澈带…

重拾Python学习,先从把python删除开始。。。

自己折腾就是不行啊&#xff0c;屡战屡败&#xff0c;最近终于找到前辈教我 第一步 删除Python 先把前阵子折腾的WSL和VScode删掉。还是得用spyder&#xff0c;跟matlab最像&#xff0c;也最容易入手。 从VScode上搞python&#xff0c;最后安装到appdata上&#xff0c;安装插…

【机器学习实战中阶】音乐流派分类-自动化分类不同音乐风格

音乐流派分类 – 自动化分类不同音乐风格 在本教程中,我们将开发一个深度学习项目,用于自动化地从音频文件中分类不同的音乐流派。我们将使用音频文件的频率域和时间域低级特征来分类这些音频文件。 对于这个项目,我们需要一个具有相似大小和相似频率范围的音频曲目数据集…

[Qt]事件-鼠标事件、键盘事件、定时器事件、窗口改变事件、事件分发器与事件过滤器

目录 前言&#xff1a;Qt与操作系统的关系 一、Qt事件 1.事件介绍 2.事件的表现形式 常见的Qt事件&#xff1a; 常见的事件描述: 3.事件的处理方式 处理鼠标进入和离开事件案例 控件添加到对象树底层原理 二、鼠标事件 1.鼠标按下和释放事件&#xff08;单击&#x…

后盾人JS -- 好用的 JavaScript Symbol 类型

Symbol使用场景介绍 举个例子&#xff0c;当leader让你去机房取某个电脑的时候&#xff0c;机房那么多电脑&#xff0c;你怎么知道取哪个 所以这个时候symbol的作用就显现出来了&#xff08;上面有什么贴纸的&#xff0c;什么型号的电脑&#xff09; 声明定义Symbol的几种方…

社区版Dify实现文生视频 LLM+ComfyUI+混元视频

社区版Dify实现文生视频 LLMComfyUI混元视频 一、 社区版Dify实现私有化混元视频效果二、为什么社区版Dify可以在对话框实现文生视频&#xff1f;LLMComfyUI混元视频 实现流程图&#xff08;重点&#xff09;1. 文生视频模型支持ComfyUI2. ComfyUI可以轻松导出API实现封装3. Di…

数智化转型 | 星环科技Defensor 助力某银行数据分类分级

在数据驱动的金融时代&#xff0c;数据安全和隐私保护的重要性日益凸显。某银行作为数字化转型的先行者&#xff0c;面临着一项艰巨的任务&#xff1a;如何高效、准确地对分布在多个业务系统、业务库与数仓数湖中的约80万个字段进行数据分类和分级。该银行借助星环科技数据安全…

Spring boot启动原理及相关组件

优质博文&#xff1a;IT-BLOG-CN 一、Spring Boot应用启动 一个Spring Boot应用的启动通常如下&#xff1a; SpringBootApplication Slf4j public class ApplicationMain {public static void main(String[] args) {ConfigurableApplicationContext ctx SpringApplication.…

中国石油大学(华东)自动评教工具(涵盖爬虫的基础知识,适合练手)

我开发了一个用于自动评教的工具&#xff0c;大家可以试着用用&#xff0c;下面是链接。 https://github.com/restrain11/auto_teachingEvaluate 可以点个星吗&#xff0c;感谢&#xff01;&#x1fae1; 以下是我在开发过程中学到的知识 以及 碰到的部分问题 目录 动态爬虫和静…

PyTorch使用教程(2)-torch包

1、简介 torch包是PyTorch框架最外层的包&#xff0c;主要是包含了张量的创建和基本操作、随机数生成器、序列化、局部梯度操作的上下文管理器等等&#xff0c;内容很多。我们基础学习的时候&#xff0c;只有关注张量的创建、序列化&#xff0c;随机数、张量的数学数学计算等常…

机器学习-距离的度量方法

文章目录 一. 欧式距离二. 曼哈顿距离三. 切比雪夫距离四. 闵式距离1. p不同取值,表示不同距离2. 当 ( p → ∞ ) ( p \to \infty ) (p→∞) 时&#xff0c;为什么闵式距离变为切比雪夫距离 五. 总结 一. 欧式距离 欧式距离&#xff08;Euclidean distance&#xff09;:多维空…

ComfyUI 矩阵测试指南:用三种方法,速优项目效果

在ComfyUI中&#xff0c;矩阵测试也叫xyz图表测试&#xff0c;作用是通过控制变量的方式来对Lora模型以及各种参数开展测试&#xff0c;并进行有效区分。其中测试方法有很多种&#xff0c;可以通过借助插件也可以自行搭建工作流实现&#xff0c;下面介绍3种方式&#xff1a; 1…

内存与缓存:保姆级图文详解

文章目录 前言1、计算机存储设备1.1、硬盘、内存、缓存1.2、金字塔结构1.3、数据流通过程 2、数据结构内存效率3、数据结构缓存效率 前言 亲爱的家人们&#xff0c;创作很不容易&#xff0c;若对您有帮助的话&#xff0c;请点赞收藏加关注哦&#xff0c;您的关注是我持续创作的…

UllnnovationHub,一个开源的WPF控件库

目录 UllnnovationHub1.项目概述2.开发环境3.使用方法4.项目简介1.WPF原生控件1.Button2.GroupBox3.TabControl4.RadioButton5.SwitchButton6.TextBox7.PasswordBox8.CheckBox9.DateTimePicker10.Expander11.Card12.ListBox13.Treeview14.Combox15.Separator16.ListView17.Data…

【STM32-学习笔记-10-】BKP备份寄存器+时间戳

文章目录 BKP备份寄存器Ⅰ、BKP简介1. BKP的基本功能2. BKP的存储容量3. BKP的访问和操作4. BKP的应用场景5. BKP的控制寄存器 Ⅱ、BKP基本结构Ⅲ、BKP函数Ⅳ、BKP使用示例 时间戳一、Unix时间戳二、时间戳的转换&#xff08;time.h函数介绍&#xff09;Ⅰ、time()Ⅱ、mktime()…

Flowable 管理各业务流程:流程设计器 (获取流程模型 XML)、流程部署、启动流程、流程审批

文章目录 引言I 表结构主要表前缀及其用途核心表II 流程设计器(Flowable BPMN模型编辑器插件)Flowable-UIvue插件III 流程部署部署步骤例子:根据流程模型ID部署IV 启动流程启动步骤ACT_RE_PROCDEF:流程定义相关信息例子:根据流程 ID 启动流程V 流程审批审批步骤Flowable 审…