学习目标
- 了解什么是电池管理单元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外设总线的供电
- 内存
-
省电模式
总共有三个省电模式:
睡眠模式
- 深度睡眠模式
-
睡眠模式
睡眠模式时,会关闭 1.2V域中的 Cortex-M4的供电。
深度睡眠模式
进入深度模式时,会关闭 1.2V域中的所有供电;同时关闭VDD/VDDA域中的
HXTAL``IRC16M``PLLs
待机模式
进入待机模式时,会关闭1.2V域中的所有供电;同时关闭VDD/VDDA域中的LDO、IRC16M、HXTAL、PLLs;
几种模式总结
案例需求

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


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

- 为PA0配置外部中断按键,按下时LED3自动切换开关
模式初始化
```c static void sleep_mode() { // 电池管理单元时钟 rcu_periph_clock_enable(RCU_PMU); // 进入睡眠模式 pmu_to_sleepmode(WFI_CMD);
}
```cstatic void deepsleep_mode() {// 电池管理单元时钟rcu_periph_clock_enable(RCU_PMU);// 进入深度睡眠模式pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, PMU_LOWDRIVER_ENABLE, WFI_CMD);}
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"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);}static void standby_mode() {// 电池管理单元时钟rcu_periph_clock_enable(RCU_PMU);pmu_wakeup_pin_enable();// 进入待机模式pmu_to_standbymode();}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();}}static void EXTI0_config() {uint32_t extix = EXTI_0;uint32_t extix_irq = EXTI0_IRQn;uint32_t extix_irq_pre = 1;uint32_t extix_irq_sub = 1;uint32_t extix_trig = EXTI_TRIG_BOTH;uint32_t extix_port_rcu = RCU_GPIOA;uint32_t extix_port = GPIOA;uint32_t extix_pin = GPIO_PIN_0;uint32_t extix_src_port = EXTI_SOURCE_GPIOA;uint32_t extix_src_pin = EXTI_SOURCE_PIN0;/*************** gpio ****************/// PA0,// 时钟初始化rcu_periph_clock_enable(extix_port_rcu);// 配置GPIO模式gpio_mode_set(extix_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, extix_pin);/*************** exti ****************/// 时钟配置rcu_periph_clock_enable(RCU_SYSCFG);// 配置中断源syscfg_exti_line_config(extix_src_port, extix_src_pin);// 中断初始化exti_init(extix, EXTI_INTERRUPT, extix_trig);// 配置中断优先级nvic_irq_enable(extix_irq, extix_irq_pre, extix_irq_sub);// 使能中断exti_interrupt_enable(extix);// 清除中断标志位exti_interrupt_flag_clear(extix);}static void EXTI1_config() {uint32_t extix = EXTI_1;uint32_t extix_irq = EXTI1_IRQn;uint32_t extix_irq_pre = 1;uint32_t extix_irq_sub = 1;uint32_t extix_trig = EXTI_TRIG_BOTH;uint32_t extix_port_rcu = RCU_GPIOD;uint32_t extix_port = GPIOD;uint32_t extix_pin = GPIO_PIN_1;uint32_t extix_src_port = EXTI_SOURCE_GPIOD;uint32_t extix_src_pin = EXTI_SOURCE_PIN1;/*************** gpio ****************/// PA0,// 时钟初始化rcu_periph_clock_enable(extix_port_rcu);// 配置GPIO模式gpio_mode_set(extix_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, extix_pin);/*************** exti ****************/// 时钟配置rcu_periph_clock_enable(RCU_SYSCFG);// 配置中断源syscfg_exti_line_config(extix_src_port, extix_src_pin);// 中断初始化exti_init(extix, EXTI_INTERRUPT, extix_trig);// 配置中断优先级nvic_irq_enable(extix_irq, extix_irq_pre, extix_irq_sub);// 使能中断exti_interrupt_enable(extix);// 清除中断标志位exti_interrupt_flag_clear(extix);}void EXTI0_IRQHandler() {// 判断寄存器状态if(SET == exti_interrupt_flag_get(EXTI_0)) {if(gpio_input_bit_get(GPIOA, GPIO_PIN_0) == SET){/* 按键按下操作的功能 */gpio_bit_toggle(GPIOG, GPIO_PIN_3);printf("PA0 press!\r\n");} else {/* 按键松开操作的功能 */printf("PA0 release!\r\n");}}// 清除中断标志位exti_interrupt_flag_clear(EXTI_0);}void EXTI1_IRQHandler() {// 判断寄存器状态if(SET == exti_interrupt_flag_get(EXTI_1)) {if(gpio_input_bit_get(GPIOD, GPIO_PIN_1) == SET){gpio_bit_toggle(GPIOD, GPIO_PIN_7);printf("key2 press!\r\n");} else {/* 按键松开操作的功能 */printf("key2 release!\r\n");}}// 清除中断标志位exti_interrupt_flag_clear(EXTI_1);}int main(void){systick_config();Usart0_init();EXTI0_config();EXTI1_config();// LED1rcu_periph_clock_enable(RCU_GPIOE);gpio_mode_set(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3);gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);// LED2rcu_periph_clock_enable(RCU_GPIOD);gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7);gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_7);// LED3rcu_periph_clock_enable(RCU_GPIOG);gpio_mode_set(GPIOG, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3);gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);while(1) {gpio_bit_toggle(GPIOE, GPIO_PIN_3);delay_1ms(500);}}
:::danger
注意:
中断优先级配置为NVIC_PRIGROUP_PRE2_SUB2情况下:
- 实现模式切换,体会不同模式工作情况
