• 理解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模式:

    1. #include "stm32f10x.h"
    2. void Enter_SleepMode(void) {
    3. // 以下是进入Sleep模式前的相关设置
    4. // 配置中断唤醒源等...
    5. // 设置SLEEPONEXIT位,CPU退出所有中断服务函数后直接进入睡眠模式
    6. SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
    7. // 进入Sleep模式
    8. __WFI(); // 使用WFI指令进入Sleep模式
    9. }

    Stop模式:

    1. #include "stm32f10x.h"
    2. #include "stm32f10x_pwr.h"
    3. #include "stm32f10x_rcc.h"
    4. void Enter_StopMode(void) {
    5. // 先关闭所有用不到的外设的时钟以节省能耗
    6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
    7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, DISABLE);
    8. // 其它外设时钟也要关闭
    9. // 配置中断唤醒源等...
    10. // 进入Stop模式
    11. PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
    12. }

    Standby模式:

    1. #include "stm32f10x.h"
    2. #include "stm32f10x_pwr.h"
    3. #include "stm32f10x_rcc.h"
    4. void Enter_StandbyMode(void) {
    5. // 配置唤醒引脚或RTC等唤醒源
    6. // 设置PDDS位进入Standby模式
    7. PWR->CR |= PWR_CR_PDDS;
    8. // 清除Wake-up标志
    9. PWR->CR |= PWR_CR_CWUF;
    10. // 进入Standby模式
    11. __WFI();
    12. }

    Shutdown模式:

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

    注意事项:

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


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


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


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


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

    唤醒操作实战代码

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

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

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

    1. #include "stm32f10x.h"
    2. #include "misc.h"
    3. void EXTI0_IRQHandler(void) {
    4. if(EXTI_GetITStatus(EXTI_Line0) != RESET) {
    5. // 执行唤醒后的操作
    6. // ...
    7. // 清除中断标志位
    8. EXTI_ClearITPendingBit(EXTI_Line0);
    9. }
    10. }
    11. void Configure_EXTI(void) {
    12. NVIC_InitTypeDef NVIC_InitStructure;
    13. EXTI_InitTypeDef EXTI_InitStructure;
    14. // Configure NVIC
    15. NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // Enable external interrupt channel
    16. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0; // Preemption Priority
    17. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0; // Sub Priority
    18. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // Enable interrupt channel
    19. NVIC_Init(&NVIC_InitStructure);
    20. // Configure EXTI Line0
    21. EXTI_InitStructure.EXTI_Line = EXTI_Line0; // Line0
    22. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // Interrupt mode
    23. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // Rising edge trigger
    24. EXTI_InitStructure.EXTI_LineCmd = ENABLE; // Enable line
    25. EXTI_Init(&EXTI_InitStructure);
    26. }
    27. void Enter_StopMode(void) {
    28. // 配置中断和停止模式等...
    29. // 进入Stop模式
    30. PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
    31. }
    32. int main(void) {
    33. // 初始化代码,配置GPIO等...
    34. Configure_EXTI();
    35. Enter_StopMode();
    36. while(1) {
    37. // 微控制器醒来后会继续在这里执行
    38. }
    39. }

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

    以RTC唤醒作为例:

    1. #include "stm32f10x.h"
    2. #include "stm32f10x_rtc.h"
    3. #include "stm32f10x_pwr.h"
    4. #include "misc.h"
    5. void RTC_IRQHandler(void) {
    6. if(RTC_GetITStatus(RTC_IT_ALR) != RESET) {
    7. // 执行唤醒后的操作
    8. // ...
    9. // 清除RTC闹钟中断
    10. RTC_ClearITPendingBit(RTC_IT_ALR);
    11. // 等待最近一次对RTC寄存器的写操作完成
    12. RTC_WaitForLastTask();
    13. }
    14. }
    15. void Configure_RTC(uint32_t time) {
    16. // 启用PWR和BKP时钟
    17. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    18. // 允许访问备份寄存器
    19. PWR_BackupAccessCmd(ENABLE);
    20. // 备份寄存器复位
    21. BKP_DeInit();
    22. // 启用LSE
    23. RCC_LSEConfig(RCC_LSE_ON);
    24. // 等待直到LSE稳定
    25. while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {}
    26. // 设置RTC时钟源
    27. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
    28. // 启用RTC
    29. RCC_RTCCLKCmd(ENABLE);
    30. // 等待RTC寄存器同步
    31. RTC_WaitForSynchro();
    32. // 等待最近一次对RTC寄存器的写操作完成
    33. RTC_WaitForLastTask();
    34. // 设置RTC预分频器,设置时钟为1Hz
    35. RTC_SetPrescaler(32767);
    36. // 等待最近一次对RTC寄存器的写操作完成
    37. RTC_WaitForLastTask();
    38. // 设置唤醒时间
    39. RTC_SetAlarm(time);
    40. // 等待最近一次对RTC寄存器的写操作完成
    41. RTC_WaitForLastTask();
    42. // 允许闹钟中断
    43. RTC_ITConfig(RTC_IT_ALR, ENABLE);
    44. // 等待最近一次对RTC寄存器的写操作完成
    45. RTC_WaitForLastTask();
    46. }
    47. int main(void) {
    48. NVIC_InitTypeDef NVIC_InitStructure;
    49. // 配置中断
    50. NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    51. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    52. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    53. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    54. NVIC_Init(&NVIC_InitStructure);
    55. // 配置RTC唤醒
    56. Configure_RTC(5); // 设置闹钟在5秒钟后触发
    57. Enter_StopMode();
    58. while(1) {
    59. // 微控制器醒来后会继续在这里执行
    60. }
    61. }

  • 相关阅读:
    Pandas行列转换
    前端设计模式——模板方法模式
    树的前序遍历非递归思路
    Redis管理客户端,兼容Windows、Mac、Linux
    青岛数字孪生赋能工业制造,加速推进制造业数字化转型
    亚马逊添加购物车和收藏有什么区别
    CSS属性:定位属性+案例讲解:博雅互动 前端开发入门笔记(五)
    C# 异步操作汇总
    python计算机毕业设计基于django的空闲教室爬虫系统
    ubuntu16.04下thrift安装及遇到的问题
  • 原文地址:https://blog.csdn.net/weixin_40345245/article/details/136607289