理解STM32的低功耗模式

低功耗模式简介

TM32的低功耗模式是特别设计来减少微控制器在不活跃状态下的能耗。这些模式允许STM32在保持核心功能的同时尽可能减少电力消耗,适合用在电池供电或需长期运行的场景。理解各种低功耗模式如何节能,主要包括以下几个方面:


关闭时钟信号:在微控制器非活跃阶段关闭CPU和不必要外围设备的时钟信号,减少硬件运行所消耗的能量。
降低工作频率:通过降低微控制器的工作频率,减少能量消耗。
停止不必要的外围设备:如果外围设备(如ADC,通讯接口)暂时不需要,将它们关闭或设置成低能耗状态。
利用休眠状态:在设备不需要执行任务时进入休眠状态,某些模块和处理器核心完全关闭,仅保持极少量电路活跃以保持必要状态或等待唤醒信号。
唤醒机制:在需要的时候,可以通过外部事件(如按键、定时器或其他中断源)快速唤醒微控制器。


通过对这些策略的应用,可以使STM32在不牺牲功能性的情况下,有效延长电池寿命,优化能源使用。

STM32的不同低功耗模式差异

Sleep模式:

特点:在该模式下,CPU停止工作,但所有外设仍然运行,时钟继续运转。
适用场景:当应用只需要暂时关闭CPU但外围设备(如ADC,通信接口)需要继续工作时使用。


Stop模式:

特点:进入Stop模式时,CPU和核心外围设备的时钟会停止,仅有部分唤醒源仍然运行,如外部中断和某些定时器。
适用场景:适用于需要长时间等待外部事件唤醒的应用,比如等待用户输入或外部信号。


Standby模式:

特点:Standby模式会关闭CPU、外围设备和时钟,只保留唤醒逻辑和备份寄存器。电源开关电路(PWR)的电源电压监测器(PVD)继续工作,可以监视电源电压。
适用场景:当设备不需要保留RAM内容且可以从复位状态恢复时使用,常见于需要极低功耗且稀疏唤醒的应用。


Shutdown模式:

特点:这是最节能的模式,几乎所有电源都会关闭,仅保持唤醒逻辑和少部分寄存器。除了低功耗唤醒和复位电路,收发器的唤醒引脚也保持激活。
适用场景:适合于极端省电场合,可以忍受较长的启动时间。


唤醒机制

Sleep模式下的唤醒:

中断信号:任何配置好的可用中断都可以从Sleep模式唤醒STM32,包括外部GPIO中断或内部模块产生的中断。
事件:像DMA传送完成或从等待模式中的事件可以唤醒。


Stop模式下的唤醒:

外部中断:通过配置的引脚检测到外部信号变化(如按键按下)可以唤醒STM32。
RTC唤醒:实时时钟(RTC)中断或者唤醒定时器到期事件可以从Stop模式中唤醒微控制器。


Standby模式下的唤醒:

唤醒引脚(Wake-up Pin):STM32的某些引脚可以配置为唤醒引脚,当这些引脚检测到特定信号(通常是高电平或低电平信号)时可以唤醒微控制器。
RTC事件:和Stop模式类似,具有唤醒功能的RTC事件也可以用来从Standby模式唤醒。


Shutdown模式下的唤醒:

唤醒引脚:即使在Shutdown模式,某些特定的唤醒引脚也是可以配置并激活的,并可以通过边沿或电平触发来唤醒微控制器。
RTC唤醒:实时时钟设定唤醒事件是另一种常见的从Shutdown模式中唤醒STM32的方式。

实战代码示例

Sleep模式:

#include "stm32f10x.h"

void Enter_SleepMode(void) {
    // 以下是进入Sleep模式前的相关设置
    // 配置中断唤醒源等...

    // 设置SLEEPONEXIT位,CPU退出所有中断服务函数后直接进入睡眠模式
    SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
    
    // 进入Sleep模式
    __WFI(); // 使用WFI指令进入Sleep模式
}

Stop模式:

#include "stm32f10x.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"

void Enter_StopMode(void) {
    // 先关闭所有用不到的外设的时钟以节省能耗
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, DISABLE);
    // 其它外设时钟也要关闭

    // 配置中断唤醒源等...

    // 进入Stop模式
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}

Standby模式:

#include "stm32f10x.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"

void Enter_StandbyMode(void) {
    // 配置唤醒引脚或RTC等唤醒源

    // 设置PDDS位进入Standby模式
    PWR->CR |= PWR_CR_PDDS;

    // 清除Wake-up标志
    PWR->CR |= PWR_CR_CWUF;
    
    // 进入Standby模式
    __WFI();
}

Shutdown模式:

请注意,标准外设库不直接支持Shutdown模式,因为这是STM32L4系列种特有的模式,属于低功耗模式的一种。对于使用标准库的STM32F1系列,最接近于Shutdown模式的是Standby模式。

注意事项:

这些示例代码针对的是STM32F1系列的微控制器。对于其它系列(如STM32F4或STM32L4),代码会稍有不同,因为不同系列的STM32可能有轻微不同的低功耗模式功能。


在进入低功耗模式之前,通常需要关闭或配置为低能耗状态的外设,以及配置唤醒源或重置源。


上面的代码片段主要涉及到电源管理部分的代码,实际应用中还需要添加外设初始化、中断配置和必要的外围逻辑。


如需进入低功耗模式之前或唤醒后执行特定操作,请根据应用实际需要补充相关功能代码。


请根据实际的微控制器型号和开发需求,查阅对应的参考手册,在理解了每个函数和寄存器操作的含义后,将这些代码片段整合到你的项目中。

唤醒操作实战代码

进入STM32低功耗模式后,你需要提前配置好一个或多个唤醒源,并在唤醒后执行相应的操作。这些唤醒源通常包括外部中断、定时器、实时时钟(RTC)事件等。以下是如何配置唤醒源以及唤醒后如何执行特定操作的示例:

一、配置外部中断作为唤醒源

以配置GPIO为外部中断作为唤醒Stop模式为例:

#include "stm32f10x.h"
#include "misc.h"

void EXTI0_IRQHandler(void) {
    if(EXTI_GetITStatus(EXTI_Line0) != RESET) {
        // 执行唤醒后的操作
        // ...

        // 清除中断标志位
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

void Configure_EXTI(void) {
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
    
    // Configure NVIC
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // Enable external interrupt channel
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0; // Preemption Priority
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0; // Sub Priority
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // Enable interrupt channel
    NVIC_Init(&NVIC_InitStructure);
    
    // Configure EXTI Line0
    EXTI_InitStructure.EXTI_Line = EXTI_Line0; // Line0
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // Interrupt mode
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // Rising edge trigger
    EXTI_InitStructure.EXTI_LineCmd = ENABLE; // Enable line
    EXTI_Init(&EXTI_InitStructure);
}

void Enter_StopMode(void) {
    // 配置中断和停止模式等...

    // 进入Stop模式
    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}

int main(void) {
    // 初始化代码,配置GPIO等...
    Configure_EXTI();
    Enter_StopMode();
    
    while(1) {
        // 微控制器醒来后会继续在这里执行
    }
}

二、配置实时时钟(RTC)唤醒

以RTC唤醒作为例:

#include "stm32f10x.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_pwr.h"
#include "misc.h"

void RTC_IRQHandler(void) {
    if(RTC_GetITStatus(RTC_IT_ALR) != RESET) {
        // 执行唤醒后的操作
        // ...

        // 清除RTC闹钟中断
        RTC_ClearITPendingBit(RTC_IT_ALR);
        // 等待最近一次对RTC寄存器的写操作完成
        RTC_WaitForLastTask();
    }
}

void Configure_RTC(uint32_t time) {
    // 启用PWR和BKP时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    
    // 允许访问备份寄存器
    PWR_BackupAccessCmd(ENABLE);
    
    // 备份寄存器复位
    BKP_DeInit();
    
    // 启用LSE
    RCC_LSEConfig(RCC_LSE_ON);
    // 等待直到LSE稳定
    while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {}

    // 设置RTC时钟源
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
    
    // 启用RTC
    RCC_RTCCLKCmd(ENABLE);
    
    // 等待RTC寄存器同步
    RTC_WaitForSynchro();
    
    // 等待最近一次对RTC寄存器的写操作完成
    RTC_WaitForLastTask();
    
    // 设置RTC预分频器,设置时钟为1Hz
    RTC_SetPrescaler(32767);
    
    // 等待最近一次对RTC寄存器的写操作完成
    RTC_WaitForLastTask();
    
    // 设置唤醒时间
    RTC_SetAlarm(time);
    // 等待最近一次对RTC寄存器的写操作完成
    RTC_WaitForLastTask();
    
    // 允许闹钟中断
    RTC_ITConfig(RTC_IT_ALR, ENABLE);
    // 等待最近一次对RTC寄存器的写操作完成
    RTC_WaitForLastTask();
}

int main(void) {
    NVIC_InitTypeDef NVIC_InitStructure;

    // 配置中断
    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 配置RTC唤醒
    Configure_RTC(5); // 设置闹钟在5秒钟后触发
    Enter_StopMode();
    
    while(1) {
        // 微控制器醒来后会继续在这里执行
    }
}

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

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

相关文章

DenseNet笔记

📒from ©实现pytorch实现DenseNet(CNN经典网络模型详解) - 知乎 (zhihu.com) 是什么之 DenseBlock 读图: x0是inputH1的输入是x0 (input)H2的输入是x0和x1 (x1是H1的输出) Summary: 传统卷积网,网…

C语言——函数指针——函数指针数组 (详解)

函数指针数组 函数指针数组的作用 函数指针数组是一个数组,其中的每个元素都是一个函数指针。函数指针是指向函数的指针变量,可以用来调用相应的函数。函数指针数组的作用是可以根据需要动态地选择并调用不同的函数。 函数指针数组的使用场景有很多&…

C++ Standard Library简介

目录 ​编辑 引言: Boost C Libraries:截至本文编写时间最新版本 1.84.0 STL源码分析: C STL源码分析(一):STL体系结构和一些基础知识 libc: 概述 libc 入门 现状 平台和编译…

BetterDisplay for mac V2.2.5 强大的mac显示器管理开源工具

BetterDisplay是Mac OS 一个很棒的工具! 它允许您将显示器转换为完全可扩展的屏幕 管理显示器配置覆盖 允许亮度和颜色控制 提供 XDR/HDR 亮度升级(Apple Silicon 和 Intel Mac 上兼容的 XDR 或 HDR 显示器的额外亮度超过 100% - 多种方法可用&#x…

【Linux】文件系统扩展——软硬链接

目录 对文件建立软硬链接 软链接 硬链接 对文件建立软硬链接 对 log 文件建立软链接: ln -s log log.soft.link 对 test 文件建立硬链接: ln test test.hard.link log.soft.link 和 test.hard.link 在 Linux 中都只是文件名,为了方便…

springboot整合shiro的实战教程(三)

文章目录 授权实现0.页面资源授权2.代码授权方式3.方法调用授权4.授权数据持久化5. 创建dao方法6.实现service接口7.修改自定义realm 授权实现 0.页面资源授权 <%taglib prefix"shiro" uri"http://shiro.apache.org/tags" %><shiro:hasAnyRoles…

Java对接(BSC)币安链 | BNB与BEP20的开发实践(二)BNB转账、BEP20转账、链上交易监控

上一节我们主要是环境搭建&#xff0c;主要是为了能够快速得去开发&#xff0c;有些地方只是简单的介绍&#xff0c;比如ETH 、web3j等等这些。 这一节我们来用代码来实现BNB转账、BEP20转账、链上交易监控 话不多说&#xff0c;我们直接用代码实现吧 1. BNB转账 /*** BNB转…

后端八股笔记-----mysql

Mysql 聚合查询————可以用增加一个实例表解决 多表查询————可以优化sql语句进行查询 &#x1f446; 显示Using index condition的话 说明是有优化的空间 &#x1f446;唯一索引指的是类似主键这种数据内容唯一的属性 &#x1f446;图中的最后一个sql的索引…

Math类 --Java学习笔记

Math 代表数学&#xff0c;是一个工具类&#xff0c;里面提供的都是对数据进行操作的一些静态方法 Math提供的常用方法

Kafka的分区机制

Kafka的分区机制是其核心功能之一&#xff0c;旨在提高可扩展性和并行处理能力。下面概述了Kafka分区的基本概念和工作原理&#xff1a; Kafka分区基本概念 分区&#xff08;Partition&#xff09;&#xff1a;Kafka中的主题&#xff08;Topic&#xff09;可以细分为多个分区…

OD_2024_C卷_200分_7、5G网络建设【JAVA】【最小生成树】

package odjava;import java.util.Scanner;public class 七_5G网络建设 {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt(); // 基站数量&#xff08;节点数&#xff09;int m sc.nextInt(); // 基站对数量&#xff08;边数&…

【Docker】在 Ubuntu20.04 上配置 Docker 开发环境

【Docker】在 Ubuntu20.04 上配置 Docker 开发环境 1 安装 Docker2 加入 Docker 用户组 1 安装 Docker 参考文档: Link 卸载以避免冲突 for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done设…

linux中新添加一块硬盘之后,系统起不来

问题&#xff1a; 在添加磁盘之后&#xff0c;重新开机时&#xff0c;却发现无法进入系统中 原因&#xff1a; 是因为添加了新的磁盘之后&#xff0c;系统将空硬盘当作系统盘启动&#xff0c;所以无法启动系统 解决方案&#xff1a; 进入到bios&#xff0c;将系统盘的优先级…

【大厂AI课学习笔记NO.71】AI算力芯片GPU/TPU等

AI算力芯片的发展历程 人工智能&#xff08;AI&#xff09;算力芯片的发展历程紧密地跟随着AI技术的发展脚步。从早期的基于传统中央处理器&#xff08;CPU&#xff09;的计算&#xff0c;到图形处理器&#xff08;GPU&#xff09;的广泛应用&#xff0c;再到专门为AI设计的处…

01_electron入门

由于毕业论文可能需要用 electron&#xff0c;所以 Linux 驱动学习慢了下来。 一、安装 node.js 进入 node.js 官网&#xff1a;Node.js (nodejs.org) 咱们就是用稳定版&#xff0c;安装包除了安装路径自己选择外&#xff0c;一直点 Next。 安装完成后需要配置环境&#xff0c…

C++容器适配器stack、queue、priority_queue

文章目录 C容器适配器stack、queue、priority_queue1、stack1.1、stack的介绍1.2、stack的使用1.3、stack的模拟实现 2、queue2.1、queue的介绍2.2、queue的使用2.3、queue的模拟实现 3、priority_queue3.1、priority_queue的介绍3.2、priority_queue的使用3.3、仿函数3.4、pri…

Vue3+ts(day02:CompositionAPI、setup)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学&#xff0c;可以点心心支持一下哈&#xff08;笔记是根据b站上学习的尚硅谷的前端视频【张天禹老师】&#xff0c;记录一下学习笔记&#xff0c;用于自己复盘&#xff0c;有需要学…

Linux——信号

目录 什么是信号 Linux下的信号 信号的记录 信号处理的常见方式 产生信号 使用组合键产生信号&#xff08;包含core dump&#xff09; 使用系统调用向进程发送信号 由软件条件产生信号 由硬件异常产生信号 阻塞信号 内核表示 sigset_t 信号集操作函数 sigpendin…

基于粒子群(PSO)的PID控制器matlab仿真

算法实现简介 利用粒子群算法对 PID 控制器的参数进行优化设计&#xff0c;其过程如图 所示。 图中&#xff0c;粒子群算法与 Simulink 模型之间连接的桥梁是粒子&#xff08;即 PID 控制器参数&#xff09;和该粒子对应的适 应值&#xff08;即控制系统的性能指标&#xff09…

商家转账到零钱场景申请哪一个

商家转账到零钱是什么&#xff1f; 商家转账到零钱功能是指商家可以通过支付平台将资金直接转账到用户的零钱账户中。在这种情况下&#xff0c;商家不需要用户提供银行账户信息&#xff0c;而是使用支付平台的转账功能将资金直接转移到用户的零钱账户中。 商家转账到零钱的使…