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

news2025/1/24 4:11:57

目录

一、停止模式基础知识

1、进入停止模式

2、停止模式的状态

3、退出停止模式

4、SysTick定时器的影响

二、停止模式应用示例

1、示例功能和CubeMX项目配置

(1)时钟

(2)RTC

(3)ADC1

(4) NVIC

(5)DEBUG、LED1、USART6、CodeGenerator

2、软件设计

(1)KEYLED 

(2)main.h

(3)main.c

3、运行并调试


一、停止模式基础知识

1、进入停止模式

        用户可以通过执行WFI指令或WFE指令进入停止模式。进入停止模式之前,用户需要将Cortex-M4F系统控制寄存器SCR的SLEEPDEEP位置1,内部调压器可以设置为正常运行或低功耗模式。函数HAL_PWR_EnterSTOPMode()用于进入停止模式,其源代码如下:

        函数HAL_PWR_EnterSTOPMode()用于进入停止模式,其源代码如下:

void HAL_PWR_EnterSTOPMode(uint32_t Regulator,uint8_t STOPEntry)
{
    /*Check the parameters */
    assert_param(IS_PWR_REGULATOR(Regulator));
    assert_param(IS_PWR_STOP_ENTRY(STOPEntry));

    /*设置调压器的模式:根据参数Regulator设置PDDS位和LPDS位*/
    MODIFY_REG(PWR->CR,(PWR_CR_PDDS I PWR_CR_LPDS),Regulator);

    /*将Cortex系统控制寄存器SCR的SLEEPDEEP位置1*/
    SET_BIT(SCB->SCR,((uint32_t)SCB_SCR_SLEEPDEEP_Msk));

    /*Select Stop mode entry*/
    if(STOPEntry == PWR_STOPENTRY_WFI)
    {
        /*Request Wait For Interrupt */
    __WFI();
    }
    else
    {
        /*Request Wait For Event */
        __SEV();
        __WFE();
        __WFE();
    }
    /*唤醒后,将SLEEPDEEP位清零*/
    CLEAR_BIT(SCB->SCR,((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
}

        参数Regulator用于表示调压器在停止模式下的工作方式,取值为宏定义常量PWR_MAINREGULATOR_ON(调压器正常运行)或PWR_LOWPOWERREGULATOR_ON(调压器处于低功耗模式)。

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

        函数HAL_PWR_EnterSTOPMode()在进入停止模式之前,将Cortex-M4F系统控制寄存器SCR的SLEEPDEEP位置1,被唤醒后再将SLEEPDEEP位清零。

        特别地,要进入停止模式,所有EXTI线的中断挂起标志都必须清零,否则,将忽略进入停止模式的操作,而继续执行程序

        在停止模式下,可以保持或关闭Flash的电源,在进入停止模式之前,可以使用以下两个函数进行设置。

HAL_PWREX_EnableFlashPowerDown();  //关闭Flash的电源
HAL_PWREx_DisableFlashPowerDown(); //不关闭Flash的电源

2、停止模式的状态

        进入停止模式后,系统的状态如下。

  • CPU的时钟关闭,CPU停止运行,也就是程序暂停。
  • 所有1.2V域外设的时钟停止,外设停止工作。
  • ADC和DAC不会自动停止工作,需要编程使其停止。
  • 1.2V调压器开启或处于低功耗状态,所有寄存器、SRAM的内容保留。
  • Flash处于正常模式或掉电模式。
  • HSI振荡器和HSE振荡器关闭。

3、退出停止模式

        如果使用WFI指令进入停止模式,所有配置为中断模式的EXTI线都可以唤醒系统。由中断唤醒后,先执行中断的ISR,然后执行WFI指令后面的程序。

        如果使用WFE指令进入停止模式,所有配置为事件模式的EXTI线都可以唤醒系统,唤醒后执行WFE后面的程序。

        EXTI线共23根,EXTI线0:15对应于外部引脚中断,EXTI线16:22对应一些内部事件,如RTC闹钟事件、RTC周期唤醒事件等。

        从停止模式唤醒时,系统有一定的唤醒延迟时间,包括以下几个时间。

  • HSI振荡器的启动时间。系统将重新启动HSI振荡器,并且将HSI作为HCLK的时钟源。对STM32F407来说,HSI频率为16MHz,使用HSI作为时钟源的HCLK最高频率为16MHz。如果需要系统从停止模式唤醒后使用更高频率的HCLK,需要重新配置系统时钟。
  • 如果调压器处于低功耗模式,需要从低功耗模式恢复到正常模式的时间。
  • 若Flash处于掉电模式,需要从掉电模式恢复到正常模式的时间。

        在停止模式下,如果调压器处于低功耗模式、Flash处于掉电模式,则可以降低停止模式的功耗,但这同时也会增加唤醒延迟。

4、SysTick定时器的影响

        MCU进入停止模式后,将只会由EXTI中断或事件唤醒,而不受SysTick定时器的影响。此外,在进入停止模式后,所有的1.2V域外设都会停止工作,SysTick定时器其实也停止了。

二、停止模式应用示例

        本文将创建一个示例项目,测试系统的STOP模式。继续使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。一些设置参考本文作者的其他文章。

        参考文章:细说STM32F407单片机电源低功耗SleepMode模式及应用示例-CSDN博客  https://wenchm.blog.csdn.net/article/details/145226004

1、示例功能和CubeMX项目配置

        本文演示MCU的停止模式。示例的功能和操作流程如下。

  • 在主程序的while循环里,让MCU进入停止模式。
  • 使用RTC的周期唤醒中断,使MCU从停止模式唤醒,RTC唤醒周期为5s。
  • MCU从停止模式唤醒后,进行一次轮询方式ADC转换。

(1)时钟

        禁用HSE,这样做很重要,因为不这样做,依旧设置外部时钟的话,系统将不能清空EXTI的中断线标志位。将HSI直接作为HCLK时钟源,HCLK设置为16MHz。因为MCU从停止模式唤醒后,自动使用HSI作为SYSCLK时钟源,所以,如果要使用HSE或更高频率的HCLK,需要重新配置系统时钟。本示例在系统唤醒后,不再配置HCLK时钟频率,故正常运行时也使用HSI作为HCLK时钟源。

(2)RTC

        并使用LSE作为RTC的时钟源。开启RTC的周期唤醒功能,

        并设置唤醒时钟为1Hz信号,唤醒计数值为4。RTC的周期唤醒使用的是EXTI线22中断,在NVIC中开启RTC周期唤醒中断,设置其抢占优先级为1。这样设置后,每5s发生一次EXTI线22中断。

(3)ADC1

        启用ADC1的内部参考电压通道,设置为12位精度、右对齐、软件触发转换。ADC1的参数设置结果如图。

 

(4) NVIC

 

(5)DEBUG、LED1、USART6、CodeGenerator

        同参考文章。 

2、软件设计

(1)KEYLED 

        本示例工程继续引用KEYLED文件夹中的keyled.h,详见参考文章。

(2)main.h

        声明一个函数,用于EXTI线清零。 

/* USER CODE BEGIN Private defines */
void EXTI_ClearITPendingBit();
/* USER CODE END Private defines */

(3)main.c

/* USER CODE BEGIN Includes */
#include "keyled.h"
#include <stdio.h>	//用到函数sprintf()
#include <string.h>	//用到函数strlen()
/* USER CODE END Includes */
/* USER CODE BEGIN 2 */
  printf("Demo22_2_StopMode:Test Stop Mode.\r\n");
  printf("Wake up by RTC every 5s.\r\n");

  //如果配置了FSMC
  //HAL_PWREx_EnableFlashPowerDown();	//在停止模式下关闭Flash电源
  //HAL_PWREx_DisableFlashPowerDown();	//不关闭Flash电源
  /* USER CODE END 2 */
 /* USER CODE BEGIN 3 */
	LED1_OFF();								//LED1熄灭
	//以下3种清零除EXTI线pending位的方法都是正确的,确保能进入STOP模式
	//EXTI->PR = 0; 						//将EXTI线的pending位清零
	EXTI->PR = EXTI_PR_PR0 << 22; 		    //将EXTI线22的pending位清零
	//EXTI_ClearITPendingBit(EXTI_PR_PR22);	//将EXTI线22的pending位清零
	//进入停止模式, WFI指令进入
	HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_SLEEPENTRY_WFI);

	//RTC周期唤醒中断(EXTI22)唤醒系统
	LED1_ON();
	HAL_ADC_Start(&hadc1);		//使能ADC1并开始转换,内部通道参考电压
	if (HAL_ADC_PollForConversion(&hadc1,200) == HAL_OK)
	{
	  uint32_t val = HAL_ADC_GetValue(&hadc1) & 0x0000FFFF;	//12位数
	  uint32_t Volt = 3300*val;	//单位:mV
	  Volt = Volt>>12;			//除以2^12
	  printf("ADC Voltage(mV) = %ld\r\n",Volt);
	}
	HAL_ADC_Stop(&hadc1);		//停止ADC1
	HAL_Delay(500);				//消除按键抖动影响,并且使LED1亮500ms
  }
  /* USER CODE END 3 */

        在进入while循环之前,调用了函数HAL_PWREx_EnableFlashPowerDown(),这可以在MCU进入停止模式后,关闭Flash存储器的电源,进一步降低功耗。也可以不关闭Flash存储器电源,也就是调用函数HAL_PWREx_DisableFlashPowerDown()(可选)。

        在while循环里,调用函数HAL PWR EnterSTOPMode()使系统进入停止模式。必须在所有EXTI线中断的挂起标志位清零的情况下,才能进入停止模式。为此,直接将外部中断挂起标志寄存器PR的内容清零,即执行语句:

EXTI->PR =0;

        进入停止模式后,CPU停止运行,程序暂停,所有外设停止工作,但RTC仍能正常工作。停止模式可以由任意EXTI线的中断或事件唤醒,RTC的周期唤醒中断是EXTI线22。本示例中设置的RTC唤醒周期是5s,所以,在发生RTC周期唤醒中断时系统会被唤醒,但是会先执行RTC中断的ISR,也就是会执行RTC周期唤醒回调函数HAL_RTCEx_WakeUpTimerEventCallback(),这个回调函数里读取RTC当前时间并显示在串口助手上。RTC中断的ISR退出后,再继续执行WFI指令后面的程序。后面的程序用轮询方式进行一次ADC转换,将结果显示在串口助手上。ADC转换结束后停止,然后MCU又进入停止模式。

/* USER CODE BEGIN 4 */
// RTC 周期唤醒中断回调函数
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
	RTC_TimeTypeDef sTime;
	RTC_DateTypeDef sDate;
	if (HAL_RTC_GetTime(hrtc,&sTime,RTC_FORMAT_BIN) == HAL_OK)
	{
		HAL_RTC_GetDate(hrtc,&sDate,RTC_FORMAT_BIN);
		uint8_t	str[30];
		sprintf((char *)str,"%2d:%2d:%2d",sTime.Hours,sTime.Minutes,sTime.Seconds);
		//HAL_UART_Transmit(&huart6,str,strlen ((const char *)(str)),200);
		printf("RTC current time: %s\r\n",str);
	}
}

//清除EXTI线[0:22]的Pending register
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)
{
  /* Check the parameters */
  assert_param(IS_EXTI_LINE(EXTI_Line));
  EXTI->PR = EXTI_Line;
}

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

3、运行并调试

        运行时会发现:每隔5s串口助手上刷新显示一次RTC时间和ADC转换结果,LED1点亮500ms后熄灭。

        停止模式比较适合于需要周期性唤醒,执行完一些操作后又进入低功耗模式的应用。例如,网络化的温度监测,可能每隔60s才需要测量一次数据并通过网络发送出去,使用周期唤醒的停止模式就可以大大降低功耗。 

        在CubeMX里可以对本示例进行功耗计算。因为使用了16MHz的HCLK,RUN模式下的耗电流是8.78mA,STOP模式下的耗电流是280μA。如果还选用3400mAh的锂电池供电,如果一个序列中RUN模式持续10ms,STOP模式持续100ms,电池可以用4月1210小时;若修改为STOP模式持续1000ms,其他参数不变,电池可以用1年28,可见降低功耗的效果是非常明显的。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Blazor-Blazor WebAssmbly项目结构(上)

创建项目 今天我们来创建一个BlazorWebAssmbly项目&#xff0c;来看看项目结构是如何得&#xff0c;我们创建带模板得项目&#xff0c;会创建出一个demo&#xff0c;来看看项目结构。 创建的项目可以直接启动运行&#xff0c;首次启动会看见加载的过程&#xff0c;这个过程…

【2024年终总结】我与CSDN的一年

&#x1f449;作者主页&#xff1a;心疼你的一切 &#x1f449;作者简介&#xff1a;大家好,我是心疼你的一切。Unity3D领域新星创作者&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6; &#x1f449;记得点赞 &#x1f44d; 收藏 ⭐爱你们&#xff0c;么么哒 文章目录 …

开篇:吴恩达《机器学习》课程及免费旁听方法

课程地址&#xff1a; Machine Learning | Coursera 共包含三个子课程 Supervised Machine Learning: Regression and Classification | Coursera Advanced Learning Algorithms | Coursera Unsupervised Learning, Recommenders, Reinforcement Learning | Coursera 免费…

推荐一个开源的轻量级任务调度器!TaskScheduler!

大家好&#xff0c;我是麦鸽。 这次推荐一款轻量级的嵌入式任务调度器&#xff0c;目前已经有1.4K的star&#xff0c;这个项目比较轻量化&#xff0c;只有5个源文件&#xff0c;可以作为学习的一个开源项目。 核心文件 项目概述&#xff1a; 这是一个轻量级的协作式多任务处理&…

暑期实习准备:C语言(持续更新)

1.局部变量和全局变量 局部变量的作用域是在变量所在的局部范围&#xff0c;全局变量的作用域是整个工程&#xff1b;局部变量的生命周期是作用域内&#xff0c;全局变量的生命周期是整个程序的生命周期&#xff0c;当两者命名冲突时&#xff0c;优先使用的是局部变量。 2.C语言…

Harmony Next 支持创建分身

应用分身能实现在一个设备上安装多个相同的应用&#xff0c;实现多个账号同时登录使用和运行并且互不影响。主要应用场景有社交账号双开、游戏大小号双开等&#xff0c;无需账号切换&#xff0c;从而省去频繁登录的繁琐。 Harmony Next 很容易就能让 App 支持创建分身。 官方文…

java ,springboot 对接支付宝支付,实现生成付款二维码,退款,查询订单状态等接口

查看文档 支付宝文档地址&#xff1a; 小程序文档 - 支付宝文档中心 使用沙箱环境 沙箱登录地址 登录 - 支付宝 点击查看 才能看钥匙截图写错了。。 问号可以看默认加密方式 点击沙箱帐号 这里我们就具备所有条件了 实战开始 pom文件增加依赖 <dependency> <gro…

深入内核讲明白Android Binder【三】

深入内核讲明白Android Binder【三】 前言一、服务的获取过程内核源码解析1. 客户端获取服务的用户态源码回顾2. 客户端获取服务的内核源码分析2.1 客户端向service_manager发送数据1. binder_ioctl2. binder_ioctl_write_read3. binder_thread_write4. binder_transaction4.1 …

chrome游览器JSON Formatter插件无效问题排查,FastJsonHttpMessageConverter导致Content-Type返回不正确

问题描述 chrome游览器又一款JSON插件叫JSON Formatter&#xff0c;游览器GET请求调用接口时&#xff0c;如果返回的数据是json格式&#xff0c;则会自动格式化展示&#xff0c;类似这样&#xff1a; 但是今天突然发现怎么也格式化不了&#xff0c;打开一个json文件倒是可以格…

canvas基础

今天我们简单的来认识学习一下canvas的基础概念和使用方法。 1. 认识canvas 1.1 什么是canvas 在网页开发中&#xff0c;canvas是html5中的一个元素&#xff0c;用于通过JavaScript绘制图形。它可以用来制作简单的图表、动画和游戏等。 1.2. 使用场景 游戏开发&#xff1a…

OneData体系架构详解

阿里巴巴的 OneData 体系架构方法论&#xff0c;主要分为三个阶段&#xff1a;业务板块、规范定义 和 模型设计。每个阶段的核心目标是确保数据的高效管理、共享与分析能力。 一. 业务板块&#xff08;Business Segment&#xff09; 业务板块是OneData体系架构中的第一步&…

【C++】哈希表的使用

unordered_map/unordered_set 这是C11才新增的两个容器 原本觉得avl树和红黑树效率已经够了。 后来探索和觉得哈希还是有必要加进来的。 JAVA里面是这样取名的&#xff1a; unordered_set unordered_map/set与map/set的功能基本一致&#xff0c;但细节上有所不同&#x…

微信小程序1.1 微信小程序介绍

1.1 微信小程序介绍 内容提要 什么是微信小程序 微信小程序的功能 微信小程序使用场景 微信小程序能取代App吗 微信小程序的发展历程 微信小程序带来的机会

前端Vue2项目使用md编辑器

项目中有一个需求&#xff0c;要在前端给用户展示内容&#xff0c;内容有 AI 生成的&#xff0c;返回来的是 md 格式&#xff0c;所以需要给用户展示 md 格式&#xff0c;并且管理端也可以编辑这个 md 格式的文档。 使用组件库 v-md-editor。 https://code-farmer-i.github.i…

26、正则表达式

目录 一. 匹配字符 .&#xff1a;匹配除换行符外的任意单个字符。 二. 位置锚点 ^&#xff1a;匹配输入字符串的开始位置。 $&#xff1a;匹配输入字符串的结束位置。 \b&#xff1a;匹配单词边界。 \B&#xff1a;匹配非单词边界。 三. 重复限定符 *&#xff1a;匹配…

K8S中Service详解(一)

Service介绍 在Kubernetes中&#xff0c;Service资源解决了Pod IP地址不固定的问题&#xff0c;提供了一种更稳定和可靠的服务访问方式。以下是Service的一些关键特性和工作原理&#xff1a; Service的稳定性&#xff1a;由于Pod可能会因为故障、重启或扩容而获得新的IP地址&a…

【真机调试】前端开发:移动端特殊手机型号有问题,如何在电脑上进行调试?

目录 前言一、怎么设置成开发者模式&#xff1f;二、真机调试基本步骤&#xff1f; &#x1f680;写在最后 前言 edge浏览器 edge://inspect/#devices 谷歌浏览器&#xff08;开tizi&#xff09; chrome://inspect 一、怎么设置成开发者模式&#xff1f; Android 设备 打开设…

初探大数据流式处理

文章目录 初探大数据流式处理批式处理系统特点流式处理系统特点大批次计算微批次计算适用场景 流式计算的应用场景流式大数据的特征流式计算的关键技术流式处理框架的特征三大流式数据处理框架 初探大数据流式处理 大数据处理系统主要分为批式处理和流式处理两类。批式处理将大…

快速搭建深度学习环境(Linux:miniconda+pytorch+jupyter notebook)

本文基于服务器端环境展开&#xff0c;使用的虚拟终端为Xshell。 miniconda miniconda是Anaconda的轻量版&#xff0c;仅包含Conda和Python&#xff0c;如果只做深度学习&#xff0c;可使用miniconda。 [注]&#xff1a;Anaconda、Conda与Miniconda Conda&#xff1a;创建和管…

部门管理查询部门,nginx反向代理,前端如何访问到后端Tomcat 注解@RequestParam

接口开发 增删改通常是不用返回data数据&#xff0c;返回null 列表查询-结果封装&#xff0c;时间 前后端联调测试 nginx反向代理&#xff0c;前端如何访问到后端Tomcat服务器 删除部门