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

ARM32开发--电源管理单元

知不足而奋进 望远山而前行


目录

文章目录

前言

学习目标

学习内容

PMU

电源域

VDD/VDDA域

备份域

1.2V域

省电模式

睡眠模式

深度睡眠模式

待机模式

几种模式总结

WFI和WFE指令

案例需求

模式初始化

源码

总结


前言

在嵌入式系统中,有效的电池管理和低功耗模式对于延长设备电池寿命至关重要。电池管理单元(PMU)及其相关的电源域和省电模式是实现这一目标的关键组成部分。本文将深入探讨PMU的功能、ARM32中的电源域结构,以及几种常见的省电模式。此外,我们还将了解如何通过在不同省电模式之间切换来优化系统功耗,同时保持系统的响应能力和功能完整性。


学习目标

  • 了解什么是电池管理单元PMU
  • 了解ARM32中的电源域
  • 了解几种省电模式

学习内容

PMU

PMU全称Power Management Unit,电源管理单元。

电源域

总共有三大电源域,包括VDD / VDDA域,1.2V域和备份域。

VDD/VDDA域

VDD/VDDA域如下图:

提供PMU 常规电源供应以下模块的供电:

  • 看门狗
  • 主频晶振
  • 内部晶振
  • ADC和DAC
  • LDO电源转换
  • 上电复位
  • 锁相环
备份域

备份域如下图:

备份域提供以下供电:

  • 外部低频时钟晶振
  • RTC
  • 上电复位
  • 电源转换
1.2V域

1.2V域如下图所示:

这个作用域主要提供:

  • AHB高速总线的供电
  • APB外设总线的供电
  • 内存
  • Cortex-M4的供电

省电模式

总共有三个省电模式:

  • 睡眠模式
  • 深度睡眠模式
  • 待机模式
睡眠模式

睡眠模式时,会关闭 1.2V域中的 Cortex-M4的供电。

深度睡眠模式

进入深度模式时,会关闭 1.2V域中的所有供电;同时关闭VDD/VDDA域中的HXTALIRC16MPLLs

待机模式

进入待机模式时,会关闭1.2V域中的所有供电;同时关闭VDD/VDDA域中的LDO、IRC16M、HXTAL、PLLs

几种模式总结

WFI和WFE指令

在ARM架构中,WFI(Wait For Interrupt)和 WFE(Wait For Event)是用于使处理器进入低功耗状态的指令。这两个指令主要用于在空闲时暂停处理器的执行,以节省功耗。

WFI指令:

WFI 指令使处理器进入等待中断状态。当处理器执行到 WFI 时,它会进入低功耗模式,直到有一个中断请求到达,将处理器唤醒。在等待中断期间,处理器会停止执行指令,以减少功耗。

WFE指令:

WFE 指令与 WFI 类似,但它不仅能够等待中断,还能够等待事件。事件是由外部设备或其他处理器触发的信号。当执行到 WFE 时,处理器会进入低功耗模式,直到有中断或事件到达,将处理器唤醒。与 WFI 不同,WFE 可以等待中断或事件中的任何一个。

案例需求

  • 让LED1 每间隔一段时间闪烁(500ms)
  • 通过串口切换 省电模式

  • 为KEY2配置外部中断按键,按下时LED1自动切换开关

  • 为PA0配置外部中断按键,按下时LED1自动切换开关
模式初始化
static void sleep_mode() {// 电池管理单元时钟rcu_periph_clock_enable(RCU_PMU);// 进入睡眠模式pmu_to_sleepmode(WFI_CMD);
}
static void deepsleep_mode() {// 电池管理单元时钟rcu_periph_clock_enable(RCU_PMU);// 进入深度睡眠模式pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, PMU_LOWDRIVER_ENABLE, WFI_CMD);// 把主频设置回来SystemInit();
}
static void standby_mode() {// 电池管理单元时钟rcu_periph_clock_enable(RCU_PMU);// 清理待机模式标记pmu_flag_clear(PMU_FLAG_RESET_STANDBY);// 启用唤醒引脚pmu_wakeup_pin_enable();// 进入待机模式pmu_to_standbymode();
}
源码
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include <string.h>
#include "main.h"
#include "USART0.h"
#include "EXTI.h"void EXTI_on_trig(exti_line_enum linex){if(linex == EXTI_1){printf("Key Trig\n");}
}void sleep_mode(){	// 睡眠模式// PMU -> RCUrcu_periph_clock_enable(RCU_PMU);printf("sleepmode1\n");// sleep modepmu_to_sleepmode(WFI_CMD);printf("sleepmode2\n");
}void deepsleep_mode(){ // 深度睡眠模式// PMU -> RCUrcu_periph_clock_enable(RCU_PMU);printf("deepsleep 1\n");// deepsleeppmu_to_deepsleepmode(PMU_LDO_LOWPOWER, PMU_LOWDRIVER_ENABLE, WFI_CMD);// 把主频设置回来SystemInit();printf("deepsleep 2\n");
}void standby_mode(){ // 待机模式// PMU -> RCUrcu_periph_clock_enable(RCU_PMU);/* 清理待机模式标记 */pmu_flag_clear(PMU_FLAG_RESET_STANDBY);/* 启用唤醒按钮 enable PMU wakeup pin */pmu_wakeup_pin_enable();printf("standby 1\n");// standby待机模式pmu_to_standbymode();printf("standby 2\n");
} void USART0_on_recv(uint8_t* data, uint32_t len) {printf("recv: %s\n", data);switch(data[0]){case 0x00:	// 睡眠模式sleep_mode();break;case 0x01:	// 深度睡眠模式deepsleep_mode();break;case 0x02:	// 待机模式standby_mode();break;default:break;}}static void GPIO_config(){// 初始化GPIO PB2rcu_periph_clock_enable(RCU_GPIOB);gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_2);gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);
}static void delay(){uint32_t i = 50000000;while(i--){__NOP();}}int main(void)
{nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
//  systick_config();USART0_init();EXTI_init();GPIO_config();printf("Main Init\n");while(1){	// 让PB2切换亮灭gpio_bit_toggle(GPIOB, GPIO_PIN_2);//		delay_ms(500);// 使用自己的睡眠函数delay();}
}

注意:

中断优先级配置为NVIC_PRIGROUP_PRE2_SUB2情况下:

  1. 串口的抢占优先级不能设置为0,否则系统无法正常睡眠,或不能正常唤醒
  2. 深度睡眠的外部中断的抢占优先级需要设置为0或1 (比串口高),否则无法正常唤醒

总结

电池管理单元(PMU)作为电源管理的核心,负责调控各种电源域,包括VDD/VDDA域、1.2V域和备份域。不同的电源域为系统的不同部分提供电源支持,保证了系统在不同工作模式下的正常运行。为了降低功耗,ARM架构中引入了几种省电模式,如睡眠模式、深度睡眠模式和待机模式,每种模式在不同场景下可以有效地降低系统的能耗。通过合理选择和配置这些省电模式,开发人员可以根据具体需求优化设备的能效和电池寿命,从而提升整体系统的性能和可靠性。

http://www.lryc.cn/news/373825.html

相关文章:

  • Android Studio项目升级报错:Namespace not specified
  • 渗透测试nginx增加400,500报错页面
  • OpenCV读取和显示和保存图像
  • 【面经总结】Java集合 - Map
  • CompletableFuture方法介绍及代码示例
  • 基于springboot的宠物商城网站
  • DM存储ontap系统修改管理IP
  • Web前端商业素材:挖掘价值,释放创意的无限可能
  • LeetCode206-反转链表
  • 5000天后的世界
  • Photoshop中颜色与色调的调整
  • 【退役之重学Java】终结篇,暂别 Java !
  • 查找——顺序查找和折半查找
  • Bio-Info每日一题:Rosalind-07-Mendel‘s First Law(孟德尔第一定律 python实现)
  • C++ 47 之 函数调用运算符重载
  • [Qt的学习日常]--常用控件1
  • 模型实战(23)之 yolov10 使用总结及训练自己的数据集
  • AIRNet模型使用与代码分析(All-In-One Image Restoration Network)
  • 欧洲杯“球迷狂欢趴”开启,容声带来“健康养鲜”新理念
  • 人工智能对零售业的影响
  • Spring Boot + EasyExcel + SqlServer 进行批量处理数据
  • 深入理解指针(四)
  • k-means聚类模型的优缺点
  • 我的创作纪念日(1825天)
  • Studio One 6.6.2 for Mac怎么激活,有Studio One 6激活码吗?
  • Windows搭建nacos集群
  • kotlin 中的字符
  • yocto根文件系统如何配置静态IP地址
  • 【博客720】时序数据库基石:LSM Tree的辅助优化
  • C++前期概念(重)