当前位置: 首页 > article >正文

STM32低功耗实验学习日记

STM32低功耗实验学习日记

写于2024/9/25晚

文章目录

  • STM32低功耗实验学习日记
    • 1. 简介
    • 2. STM32F1电源系统
      • 2.1 电源系统
      • 2.2 电源管理
        • 2.2.1 睡眠模式
        • 2.2.2 停止模式
        • 2.2.3 待机模式
      • 2.3 相关寄存器介绍
        • 2.3.1 系统控制寄存器(SCB_SCR)
        • 2.3.2 电源控制寄存器(PWR_CR)
        • 2.3.3 电源控制/状态寄存器(PWR_CSR)
        • 2.3.4 WFI与WFE指令
    • 3. 进入低功耗模式的使用步骤
    • 4. 代码解析

1. 简介

我们将介绍 STM32F103 的电源控制(PWR),并实现低功耗模式相关功能。我们将通过四个实验来学习并实现低功耗相关功能,分别是 PVD 电压监控实验、睡眠模式实验、停止模式实验和待机模式实验

2. STM32F1电源系统

电源控制部分(PWR)概述了不同电源域的电源架构以及电源配置控制器。PWR 的内容比较多,我们把它们的主要特性概括为以下 3 点:

  • 电源系统:VDDA供电区域、VDD供电区域、1.8V 供电区域、后备供电区域。

  • 电源监控:POR/PDR 监控器、PVD 监控器。

  • 电源管理:低功耗模式。

下面将分别对这 3 个特性进行简单介绍。

2.1 电源系统

image-20240925220620902

在电源概述框图中我们划分了 3 个区域①②③,分别是独立的 A/D 转换器供电和参考电压、电压调节器、电池备份区域。下面分别进行简单介绍:

① 独立的 A/D转换器供电和参考电压(VDDA供电区域)

VDDA 供电区域,主要是 ADC 电源以及参考电压,STM32 的 ADC 模块配备独立的供电方式,使用了 VDDA 引脚作为输入,使用 VSSA 引脚作为独立地连接VREF 引脚为提供给 ADC 的参考电压

② 电压调节器(VDD /1.8V供电区域)

电压调节器是 STM32 的电源系统中最核心部分,连接 VDD供电区域1.8 V供电区域。VDD供电来自于 VSS 和 VDD,给 I/O 电路以及待机电路供电,电压调节器主要为备份域以及待机电路以外的所有数字电路供电,其中包括内核、数字外设以及RAM,调节器的输出电压约为1.8V,因此由调压器供电的区域称为 1.8V 供电区域。电压调节器根据应用方式不同有三种不同的工作模式。在运行模式下,调节器以正常工作模式为内核、内存和外设提供 1.8V;在停止模式下,调节器以低功耗模式提供 1.8V 电源,以保存寄存器和 SRAM 的内容。在待机模式下,调节器停止供电,除了备用电路和备份域外,寄存器和 SRAM 的内容全部丢失。

③ 电池备份区域(后备供电区域)

电池备份区域也就是后备供电区域,使用电池或者其他电源连接到 VBAT脚上,当 VDD断电时,可以保存备份寄存器的内容维持 RTC 的功能。同时 VBAT 引脚也为 RTCLSE 振荡器供电,这保证了当主要电源被切断时,RTC 能够继续工作。切换到 VBAT 供电由复位模块中的掉电复位功能控制。

2.2 电源管理

电源管理的部分我们要关注低功耗模式,在 STM32 的正常工作中,具有四种工作模式,运行、睡眠、停止以及待机。在上电复位后,STM32 处于运行状态时,当内核不需要继续运行,就可以选择进入后面的三种模式降低功耗。

这三种低功耗模式电源消耗不同、唤醒时间不同和唤醒源不同,我们要根据自身的需要选择合适的低功耗模式。下面是低功耗模式汇总介绍,如下表所示。

image-20240925221804613

2.2.1 睡眠模式

进入睡眠模式,Cortex_M3 内核停止,所有外设包括 Cortex_M3 核心的外设,如 NVIC、系统时钟(SysTick)等仍在运行,有两种进入睡眠模式的模式 WFI 和 WFE。WFI(Wait for interrupt等待中断)和 WFE(Wait for event等待事件)是内核指令,会调用一些汇编指令,会使用即可。睡眠后唤醒的方式即由等待“中断”唤醒和“事件”唤醒。

image-20240925222025162

image-20240926215958124

2.2.2 停止模式

进入停止模式,所有的时钟都关闭,所有的外设也就停止了工作。但是 VDD电源是没有关闭的,所以内核的寄存器和内存信息都保留下来,等待重新开启时钟就可以从上次停止的地方继续执行程序。

值得注意的是:当电压调节器处于低功耗模式下,当系统从停止模式退出时,将会有一段额外的启动延时。如果在停止模式期间保持内部调节器开启,则退出启动时间会缩短,但相应的功耗会增加。

image-20240926220653052

image-20240926220842031

2.2.3 待机模式

待机模式可实现最低功耗。该模式是在 CM3 深睡眠模式时关闭电压调节器,整个 1.8V 供电区域被断电。PLL、HSI 和 HSE 振荡器也被断电。除备份域(RTC 寄存器、RTC 备份寄存器和备份 SRAM)和待机电路中的寄存器外,SRAM 和其他寄存器内容都将丢失。不过如果我们使能了备份区域(备份 SRAM、RTC、LSE),那么待机模式下的功耗,将达到 3.8uA 左右。

image-20240926220950578

image-20240926221020206

image-20240926221116457

2.3 相关寄存器介绍

2.3.1 系统控制寄存器(SCB_SCR)

image-20240926221315109

2.3.2 电源控制寄存器(PWR_CR)

image-20240926221441770

2.3.3 电源控制/状态寄存器(PWR_CSR)

image-20240926222647713

2.3.4 WFI与WFE指令

image-20240926222930635

内核指令,使用函数的格式__WFI()__WFE()来调用。__wfi__wfe是编译器内置的函数,函数内部调用了相对应的汇编指令。

驱动函数关联寄存器功能描述
HAL_PWR_EnterSLEEPMode(…)SCB_SCR进入睡眠模式
HAL_PWR_EnterSTOPMode(…)PWR_CR/SCB_SCR进入停止模式
HAL_PWR_EnterSTANDBYMode(…)PWR_CR/SCB_SCR进入待机模式
HAL_PWR_EnableWakeUpPin(…)PWR_CSR使能WKUP管脚唤醒功能
__HAL_PWR_CLEAR_FLAG(…)PWR_CR清除PWR的相关标记
__HAL_RCC_PWR_CLK_ENABLE(…)RCC_APB1ENR使能电源时钟

3. 进入低功耗模式的使用步骤

image-20240926223519705

image-20240926223555882

在退出停止模式后,需要重新设置时钟、重新选择滴答时钟源、失能systick中断

image-20240926223650224

待机模式配置步骤

  1. 初始化WKUP为中断触发源
  2. 使能电源时钟:__HAL_RCC_PWR_CLK_ENABLE
  3. 使能WKUP的唤醒功能:HAL_PWR_EnableWakeUpPin
  4. 清除唤醒标记WUF:__HAL_PWR_CLEAR_FLAG
  5. 进入待机模式:HAL_PWR_EnterSTANDBYMode

4. 代码解析

驱动函数关联寄存器功能描述
HAL_PWR_EnterSLEEPMode(…)SCB_SCR进入睡眠模式
HAL_PWR_EnterSTOPMode(…)PWR_CR/SCB_SCR进入停止模式
HAL_PWR_EnterSTANDBYMode(…)PWR_CR/SCB_SCR进入待机模式
HAL_PWR_EnableWakeUpPin(…)PWR_CSR使能WKUP管脚唤醒功能
__HAL_PWR_CLEAR_FLAG(…)PWR_CR清除PWR的相关标记
__HAL_RCC_PWR_CLK_ENABLE(…)RCC_APB1ENR使能电源时钟
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/BEEP/beep.h"
#include "./BSP/KEY/key.h"
#include "./BSP/PWR/pwr.h"



void pwr_wkup_key_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    PWR_WKUP_GPIO_CLK_ENABLE();                             /* WKUP引脚时钟使能 */

    gpio_init_struct.Pin = PWR_WKUP_GPIO_PIN;               /* WKUP引脚 */
    gpio_init_struct.Mode = GPIO_MODE_IT_RISING;            /* 中断,上升沿 */
    gpio_init_struct.Pull = GPIO_PULLDOWN;                  /* 下拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */
    HAL_GPIO_Init(PWR_WKUP_GPIO_PORT, &gpio_init_struct);   /* WKUP引脚初始化 */

    HAL_NVIC_SetPriority(PWR_WKUP_INT_IRQn, 2, 2);          /* 抢占优先级2,子优先级2 */
    HAL_NVIC_EnableIRQ(PWR_WKUP_INT_IRQn); 
}

void PWR_WKUP_INT_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(PWR_WKUP_GPIO_PIN);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == PWR_WKUP_GPIO_PIN)
    {
        /* HAL_GPIO_EXTI_IRQHandler()函数已经为我们清除了中断标志位,所以我们进了回调函数可以不做任何事 */
    }
}


int main(void)
{
    uint8_t key;
    uint8_t t = 0;
    
    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    delay_init(72);                         /* 延时初始化 */
    usart_init(115200);                     /* 串口初始化 */
    led_init();                             /* 初始化LED */
    key_init();                             /* 初始化按键 */
    pwr_wkup_key_init();                    /* WKUP引脚初始化 */
    pwr_pvd_init();                         /* PVD配置 */
    
    printf("Enter to LowPower Test \r\n");
    
    while(1)
    {
        key = key_scan(0);                  /* 得到键值 */

        if (key)
        {
            switch (key)
            {
                /* 进入待机模式 */
                case KEY2_PRES:
                
                    /* 使能电源时钟 */
                    __HAL_RCC_PWR_CLK_ENABLE();
                
                    /* 使能WKUP上升沿的唤醒功能 */
                    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
                
                    /* 清除唤醒标记 */
                    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
                
                    printf("Enter STANDBY Mode \r\n");
                    
                    HAL_PWR_EnterSTANDBYMode();
                
                    printf("Exit STANDBY Mode \r\n");

                    break;

                /* 进入停止模式 */
                case KEY1_PRES:
                    
                    LED1(0);        /* 点亮绿灯,提示进入停止模式 */
                    
                    printf("Enter STOP Mode \r\n");
                    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
                    
                    sys_stm32_clock_init(RCC_PLL_MUL9);     /* 重新设置时钟, 72Mhz */
                    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8);
                    HAL_SuspendTick();
                
                    printf("Exit STOP Mode \r\n");
                
                    LED1(1);
                    break;
                
                /* 进入睡眠模式 */
                case KEY0_PRES:
                    
                    printf("Enter SLEEP Mode \r\n");
                    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
                    printf("Exit SLEEP Mode \r\n");
                
                    break;
            } 
        }
        
        if ((t % 20) == 0)
        {
            LED0_TOGGLE();              /* 每200ms,翻转一次LED0 */
        }

        delay_ms(10);
        t++;
    
    }
}



http://www.kler.cn/news/329035.html

相关文章:

  • GO语言环境搭建和字符说明
  • 【Linux系统编程】第二十六弹---彻底掌握文件I/O:C/C++文件接口与Linux系统调用实践
  • 中国身份证号码校验
  • python和r语言的区别是什么
  • alpine安装docker踩坑记
  • git初级使用学习(图文)
  • uniapp微信小程序使用ucharts遮挡自定义tabbar的最佳解决方案
  • Windows 11 的 24H2 更新將帶來全新 Copilot+ AI PC 功能
  • linux文本三剑客
  • 【SQLite】sqlite | insert插入存在即更新
  • 828华为云征文 | 华为云X实例CPU性能测试详解与优化策略
  • Android Studio :The emulator process for AVD was killed。
  • 微服务--SpringAMQP
  • YOLOv5改进:Unified-loU,用于高品质目标检测的统一loU ,2024年8月最新IoU
  • 【嵌入式linux】GPIO子系统 | 用户空间交互
  • 使用 Nginx 和 Gunicorn 部署 Flask 项目详细教程
  • 《论文阅读》PECER:通过动态人格提取和情境情绪推理产生同理心反应 ICASSP 2024
  • Spring1
  • golang学习笔记21-面向对象(三):封装与继承【重要】
  • Spring Boot助力IT领域交流平台开发
  • ffmpeg拉取rtsp网络视频流报错解析
  • XPath基础知识点讲解——用于在XML中查找信息的语言
  • Redis 篇-深入了解 Redis 中的 RESP 通信协议与内存回收(过期 key 处理、内存淘汰策略)
  • CentOS系统yum出现Could not retrieve mirrorlist问题
  • G502 鼠标自定义(配合 karabiner)
  • 【算法竞赛】堆
  • 前端框架中@路径别名原理和配置
  • 在线代码编辑器
  • 【数据库】在 Java 中使用 MongoDB 进行数据聚合
  • 【系统代码】招投标采购一体化管理系统,JAVA+vue