1. 简介
PMU电源管理单元通俗讲就是用来管理MCU的电源域的,它主要有两个功能——电压监测和低功耗管理。在GD32中一共有3个电源域——VDD/VDDA域、1.2V域和备份域。
VDD/VDDA域主要供PMU控制器、ADC、DAC等外设使用;1.2V域就是大部分外设都会使用的电源域,像芯片核心、AHB外设、APB外设;备份域主要供RTC外设使用。
2. 低功耗模式
低功耗模式是PMU的重要功能,也是我们平时用得最多的。在GD32F4中,一共有3种低功耗模式——睡眠模式、深度睡眠模式和待机模式。模式从左到右会越来越省电。
2.1 睡眠模式
睡眠模式仅仅关闭核心电压,日常应用中用得会比较少,毕竟外设才是耗电大户,节省核心的耗电基本没啥用。睡眠模式可以设置中断唤醒或事件唤醒,所有的中断或事件都能唤醒。进入睡眠模式还可以设置立即进入或稍后进入,设置为稍后进入的话系统会等待所有的中断都处理完才进入睡眠。
2.2 深度睡眠模式
深度睡眠模式会关闭1.2V域中的所有时钟,VDD/VDDA域中的高速外部时钟、高速内部时钟和锁相环也会关闭;但SRAM和寄存器中的内容仍能保存。同样,该模式可以设置中断唤醒或事件唤醒,所有的中断或事件都能唤醒。进入深度睡眠模式的同时还可以设置低驱动模式,进一步降低功耗。这个模式也是应用中用得最多的模式。
2.3 待机模式
待机模式就相当于是关机了,在深度睡眠的基础上连1.2V域的电源都断掉了,这意味着SRAM和寄存器的数据就不能保存了,所以待机模式唤醒之后,程序只能从头开始执行。要想从待机模式唤醒只有4种方法——NRST引脚复位、WAKEUP引脚唤醒、独立看门狗复位和RTC唤醒。
3. 例程
3.1 深度睡眠
深度睡眠我们配置外部按键事件进行唤醒。GPIO、EXTI的配置可以参考之前的文章,唯一有区别的是,因为我这里使用的是事件唤醒。不得不说GD的固件比ST的好多了,PMU的配置除了使能时钟外就一个语句的事。要注意的是,深度睡眠会关闭外设的时钟,所以唤醒后要重新使能外设时钟,不然外设是不工作的。
int main(void)
{
systick_config();
debug_init();
printf("pmu demo\r\n");
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_SYSCFG);
gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN0);
exti_init(EXTI_0, EXTI_EVENT, EXTI_TRIG_RISING);
exti_flag_clear(EXTI_0);
exti_event_enable(EXTI_0);
rcu_periph_clock_enable(RCU_PMU);
while (1) {
printf("enter deep sleep mode\r\n");
pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, PMU_LOWDRIVER_ENABLE, WFE_CMD);
systick_config();
debug_init();
printf("exit deep sleep mode\r\n");
}
}
3.2 待机
待机例程我们也是使用按键唤醒,但是只能用PA0来唤醒;只需要做GPIO初始化即可,调pmu_wake_up_pin_enable就可以使能PA0唤醒了。进入待机也是一行代码的事,调pmu_to_standbymode即可,这个函数后面写什么就不重要了,因为唤醒之后是会复位的,程序从头开始执行。
int main(void)
{
systick_config();
debug_init();
printf("pmu demo\r\n");
rcu_periph_clock_enable(RCU_GPIOA);
gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
rcu_periph_clock_enable(RCU_PMU);
pmu_wakeup_pin_enable();
printf("enter standby mode\r\n");
pmu_to_standbymode();
while (1) {
}
}