问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

电源管理单元(PMU)详解:电源域、省电模式与案例实现

创作时间:
作者:
@小白创作中心

电源管理单元(PMU)详解:电源域、省电模式与案例实现

引用
CSDN
1.
https://blog.csdn.net/ic2121/article/details/144872010

电源管理单元(PMU)是嵌入式系统中重要的硬件模块,负责系统的电源管理和省电模式控制。本文将详细介绍PMU的各个电源域、省电模式以及如何通过代码实现不同模式的切换。

一、电源管理单元(PMU)概述

PMU全称Power Management Unit,电源管理单元。它主要负责系统的电源管理和省电模式控制。

1. 电源域

PMU包含三大电源域:

  • VDD / VDDA域

    提供以下模块的供电:

  • 看门狗

  • 主频晶振

  • 内部晶振

  • ADC和DAC

  • LDO电源转换

  • 上电复位

  • 锁相环

  • 备份域
    备份域提供以下供电:

  • 外部低频时钟晶振

  • RTC

  • 上电复位

  • 电源转换

  • 1.2V域

    主要提供:

  • AHB高速总线的供电

  • APB外设总线的供电

  • 内存

  • Cortex-M4的供电

二、省电模式介绍

1. 省电模式分类

总共有三个省电模式:

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

2. 各种模式的供电情况

  • 睡眠模式:仅关闭Cortex-M4的供电
  • 深度睡眠模式:关闭1.2V域中的所有供电;同时关闭VDD/VDDA域中的HXTAL、IRC16M、PLLs
  • 待机模式:关闭1.2V域中的所有供电;同时关闭VDD/VDDA域中的LDO、IRC16M、HXTAL、PLLs

3. 模式总结

模式
睡眠
深度睡眠
待机
描述
仅关闭CPU时钟
关闭1.2V电源域的所有时钟;关闭IRC16M、HXTAL和PLL
关闭1.2V电源域的供电;关闭IRC16M、HXTAL和PLL
LDO状态
开启(正常功耗,正常驱动模式)
开启(正常功耗或低功耗模式,正常驱动或低驱动模式)
关闭
配置
SLEEPDEEP=0
SLEEPDEEP=1,STBMOD =0
SLEEPDEEP=1,STBMOD=1,WURST=1
进入指令
WFI或WFE
WFI或WFE
WFI或WFE
唤醒
任何中断
EXTI中断
NRST引脚、WKUP引脚、FWDGT复位、RTC
唤醒延迟
IRC16M唤醒时间(可能包含LDO唤醒时间)
上电序列

三、WFI和WFE指令

在ARM架构中,WFI(Wait For Interrupt)和WFE(Wait For Event)是用于使处理器进入低功耗状态的指令。

  • WFI指令:使处理器进入等待中断状态,直到有中断请求到达。
  • WFE指令:使处理器进入等待中断或事件状态,可以等待中断或事件中的任何一个。

四、案例需求

本案例实现以下功能:

  • 让LED1每间隔500ms闪烁
  • 通过串口切换省电模式
  • 通过按键切换LED2和LED3的状态

五、模式初始化

1. 睡眠模式

static void sleep_mode() {
    // 电池管理单元时钟
    rcu_periph_clock_enable(RCU_PMU);
    // 进入睡眠模式
    pmu_to_sleepmode(WFI_CMD);
}

2. 深度睡眠模式

static void deepsleep_mode() {
    // 电池管理单元时钟
    rcu_periph_clock_enable(RCU_PMU);
    // 进入深度睡眠模式
    pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, PMU_LOWDRIVER_ENABLE, WFI_CMD);
}

3. 待机模式

static void standby_mode() {
    // 电池管理单元时钟
    rcu_periph_clock_enable(RCU_PMU);
    pmu_wakeup_pin_enable();
    // 进入待机模式
    pmu_to_standbymode();
}

六、完整源码

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "Usart0.h"

// 省电模式函数定义(略)

void Usart0_on_recv(uint8_t* data, uint32_t len) {
    printf("recv: %s\r\n", data);

    if(data[0] == 0x00) {
        printf("sleep mode \r\n");
        sleep_mode();
    } else if(data[0] == 0x01) {
        printf("deepsleep mode \r\n");
        deepsleep_mode();
        SystemInit();
    } else if(data[0] == 0x02) {
        printf("standby mode \r\n");
        standby_mode();
    }
}

// EXTI配置函数定义(略)

void EXTI0_IRQHandler() {
    // EXTI0中断处理(略)
}

void EXTI1_IRQHandler() {
    // EXTI1中断处理(略)
}

int main(void)
{
    systick_config();
    Usart0_init();
    EXTI0_config();
    EXTI1_config();

    // LED初始化(略)

    while(1) {
        gpio_bit_toggle(GPIOE, GPIO_PIN_3);
        delay_1ms(500);
    }
}

七、注意事项

  • 中断优先级配置为NVIC_PRIGROUP_PRE2_SUB2情况下:
  • 串口的抢占优先级不能设置为0,否则系统无法正常睡眠
  • 深度睡眠的外部中断的抢占优先级必须设置为0或1,否则无法正常唤醒

八、总结

  • 普通睡眠:任何中断都会唤醒。
  • 深度睡眠: 唤醒中断睡眠优先级要高一些。
  • 待机:会重启,不会走下面。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号