一种基于GD32L23X的低功耗运作模式
采用GD32L23X的DEEP-SLEEP1,1hz的RTC唤醒,休眠前需要对除特定GPIO外所有的GPIO配置成模拟模式,并且关闭所有外设退出休眠,最终可以到到休眠时15uA,运行时2mA的功耗。
1.GD32电源管理单元PMU
(1)3种电源域的概念:
GD32L23X提供3种电源域 :VDD / VDDA domain, 1.1V domain, and Backup domain,
1.VDD / VDDA domain
VDD/ VDDA domain基本外设 :
HXTAL , LDO, POR / PDR (power on / down Reset),
FWDGT (free watchdog timer), all pads except PC13 / PC14 / PC15, etc.
VDDA domain includes ADC / DAC ,RC16M, IRC48M,
IRC32K ,PLLs (phase locking loop),
LVD (low voltage detector), etc.
VDD 不同模式下工作状态
run模式:1.1V全电源开启
sleep模式(1.1V全电源开启、0.9V全电源开启、低功率)、
深度睡眠/深度睡眠1/深度睡眠2模式(开启或低功率)
待机模式(断电)
1.1V power domain
SRAM1 power domain
SRAM1 可以被单独关闭以达到减小功耗的作用,GD32L233包括两种SRAM,SRAM1(16KB)地址:0x20005000 - 0X20007FFFF 0x20004000 - 0x20004FFF
SRAM0(16KB)地址:0x20002000 - 0x20003FFF 0x20001000 - 0x20001FFF
0x2000000 - 0x20000FFF
COREOFF1 power domain
可以被单独关闭,包括了CAU单元(加密加速单元)
COREOFF0 power domain
进入深度睡眠2模式时,COREOFF0电源域已关闭,退出深度睡眠2模式时已开机。COREOFF0 power域包括以下模块:CPU/BUS/ADC/CMP/CRC/CTC/CAC/I2C0/I2C1/SLCD/TRNG/TRNG/SPI0/SPI1/TIMER1/TIMER2/TIMER5/TIMER6/TIMER8/TIMER11/USART0/USART1/USART3/USART4/USBD
当进入/退出深度睡眠2模式时,可以通过在PMU_CTL1寄存器中配置NRRD2位来保留或不保留CPU寄存器
Battery backup domain
基本外设:LXTAL RTC BPOR BKP PAD(PC13,PC14, PC15)COREOFF0
能够断电重置后保存RTC时间,并且可以切换给VBAT电池供电,用电池供电后,可以保存
低功耗模式
电源管理单元PMU提供10种模式进行低功耗,如下:
低功耗模式 | 特点 | 理论耗电量 |
---|---|---|
Run mode | NPLDO工作在1.1V模式 | 68 - 146uA/Mhz |
Run1 mode | NPLDO工作在0.9V模式 系统时钟最大只能16MHZ | 48 - 119uA/Mhz |
Run2 mode | NPLDO工作在0.9V模式 系统时钟最大只能2MHZ | 220uA |
Sleep mode | 提供最低唤醒时间 | 36-120uA/Mhz |
Sleep1 mode | NPLDO应该被选择为0.9V。 | 32.5-109uA/Mhz |
Sleep2 mode | NPLDO应该被选择为0.9V。PMU_CTL0中的LDNP应该配置为选择低密度模式, | 210 -430uA |
Deep-sleep mode | 1.1V域中的所有时钟都被关闭,所有的IRC16M、IRC48M、HXTAL和pll都被禁用,LDO在低驱动模式下启动可能产生额外延时,退出深度睡眠模式时,会选IRC16M作为系统时钟 | <40uA |
Deep-sleep 1 mode | 1.1V域中的所有时钟都被关闭,所有的IRC16M、IRC48M、HXTAL和pll都被禁用,LDO启动将产生额外延时,退出深度睡眠模式时,会选IRC16M作为系统时钟 | 3.14uA |
Deep-sleep 2 mode | 所有时钟都被关闭,所有的IRC16M、IRC48M、HXTAL和pll都被禁用。COREOFF0 / SRAM1 / COREOFF1域的电源被切断。COREOFF0 / SRAM1 / COREOFF1域的内容丢失 ,保留寄存器和SRAM中的数据,退出深度睡眠模式时,会选IRC16M作为系统时钟 | <1.7uA |
Standby mode | 直接关闭 1.1V 域,可以极大降低功耗,但域中寄存器 内容丢失,包括内部 RAM ,推出待机模式会发生上电复位,cotexM23从0x00000000开始执行 | 0.44uA |
WFI和WFE指令进入休眠
WFI(Wait for interrupt)和WFE(Wait for event)是两个让ARM核进入low-power standby模式的指令,由ARM architecture定义,由ARM core实现。
WFI和WFE的最大不同是WFI只能够被EXTI中断唤醒,而WFE可以被任何EXTI事件唤醒。
注意进入休眠状态一定要能够唤醒,并且给延时,否则一直进休眠导致烧录不了,具体解决措施如下:
引导源选择 | Boot1 | Boot0 |
---|---|---|
FLASH存储器 | x | 0 |
引导装载程序 | 0 | 1 |
片上SRAM | 1 | 1 |
通过镊子短接或者飞线的形式将Boot0置为1,Boot1置为0进入引导装载程序。 |
休眠唤醒为复位还是由该语句继续往下执行
LED_DISABLE
delay_1ms(2000);
pmu_to_deepsleepmode(PMU_LDNPDSP_LOWDRIVE, WFI_CMD, PMU_DEEPSLEEP2);
LED_ENABL
delay_1ms(1000);
通过上段代码在while循环里进行测试得出以下结论
休眠模式选择 | LED灯状态 | 结论 |
---|---|---|
deep-sleep mode | 灯在唤醒后闪烁 | 继续往下执行 |
deep-sleep mode1 | 灯在唤醒后闪烁 | 继续往下执行 |
deep-sleep mode2 | 灯不闪烁 | 内容丢失无法继续往下执行 |
standby mode | 灯不闪烁 | 复位 |
RTC休眠唤醒注意:
进入深度睡眠模式后,只能有EXTI中断
EXTI源:
除PC13-PC15外的所有GPIO引脚
LVD, RTC ,USBD CMP0,CMP1 I2C0, I2C2, USART0,USART1,I2C1,LPUART,LPTIMER
进行唤醒,因此RCT闹钟需要挂载到EXTI上,才可定时唤醒
记得在RTC中断中清除中断标志位
void RTC_Init(void) {
/* enable PMU and BKPI clocks */
rcu_periph_clock_enable(RCU_PMU);
rcu_periph_clock_enable(RCU_BKP);
/* allow access to BKP domain */
pmu_backup_write_enable();
rcu_periph_clock_enable(RCU_RTC);
/* enable LXTAL */
rcu_osci_on(RCU_IRC32K);
/* wait for LXTAL stabilization flag */
rcu_osci_stab_wait(RCU_IRC32K);
rcu_lxtal_clock_monitor_enable();
/* configure the RTC clock source selection */
rcu_rtc_clock_config(RCU_RTCSRC_IRC32K);
rtc_register_sync_wait();
/* setup RTC time value */
rtc_initpara.factor_asyn = prescaler_a;
rtc_initpara.factor_syn = prescaler_s;
rtc_initpara.year = 0x16;
rtc_initpara.day_of_week = RTC_WEDNESDAY;rtc_initpara.month = RTC_SEP;
rtc_initpara.date = 0x07;
rtc_initpara.display_format = RTC_24HOUR;
rtc_initpara.am_pm = RTC_AM;
rtc_initpara.hour = 0x09;
rtc_initpara.minute = 0x28;
rtc_initpara.second = 0;
rtc_init(&rtc_initpara);
/* EXTI line 20 configuration */
nvic_irq_enable(RTC_WKUP_IRQn, 2);
exti_flag_clear(EXTI_20);
exti_init(EXTI_20, EXTI_INTERRUPT, EXTI_TRIG_RISING);
rtc_flag_clear(RTC_STAT_WTF);
/* wakeup clock configuration */
rtc_wakeup_clock_set(WAKEUP_CKSPRE);
rtc_wakeup_timer_set(2);
rtc_interrupt_enable(RTC_INT_WAKEUP);
/*rtc enable*/
rtc_wakeup_enable();
}
void RTC_WKUP_IRQHandler(void){
if(RESET != rtc_flag_get(RTC_FLAG_WT)) {
/* clear EXTI line 20 pending and rtc wakeup flag */rtc_flag_clear(RTC_FLAG_WT);
exti_flag_clear(EXTI_20);
/* disable rtc auto wakeup function */
}
}
RTC闹钟和自动休眠唤醒
时钟源和分频
采用内部时钟IRC32K
平均频率: 31.7-32.3khz
工作电流: 160nA
唤醒时间: 40us
RTC提供了一定的时间,其中包括小时/分/秒/次秒,还有一个日历,包括年/月/日/周的一天。除次秒外,时间和日历都用BCD代码表示。次秒级用二进制代码表示。调整夏令时的时间。工作在省电模式和智能唤醒是软件是可配置的。支持使用外部精确低频时钟提高日历准确性。
GD32将RTC分成两部分,把内核部分(预分频器、分频器、计数器、闹钟)放在备份,达到复位重启不丢时间的目的,其它(APB1接口)放在VDD电源域
增加电池,当VDD断电后,自动切换到电池供电(VBAT),达到MCU断电不丢时间的目的
其中RTC单元有三种独立时钟源分别是:LXTAL,IRC32K和HXTAL
有2个分频器,一个7位异步分频器,另一个是一个15位同步分频器,异步分频器主要用于减少能耗,
F
=
F
C
/
(
F
A
C
T
O
R
A
+
F
A
C
T
O
R
B
)
+
1
F = F_C/(FACTOR_A +FACTOR_B)+ 1
F=FC/(FACTORA+FACTORB)+1
1HZ的自动唤醒计算32K/128/250 = 1HZ
7位异步分频器 = 128
15位同步分频器 = 250
自动唤醒挂载到EXTI_20,优先级2,闹钟Alarm挂载到EXTI_17,优先级0
GPIO低功耗配置
上下拉 40kΩ
工作频率 10MHZ 50MHZ 2MHZ可选
基本配置理解
上下拉的作用
首先 上下拉 是给IO一个默认的状态 比如控制EN的话,那么高有效的我们就下拉,低有效的话我们就上拉。
上拉就是将不确定的信号通过一个电阻钳位在高电平,电阻同时起限流作用。下拉同理。也是将不确定的信号通过一个电阻钳位在低电平。
上拉电阻有时是用来解决总线驱动能力不足时提供电流的,一般说法是拉电流;下拉电阻是用来吸收电流的,也就是灌电流。比如有I2C总线使用会上拉一个10k的电阻。
施密特触发器的作用
施密特触发器在GPIO中的作用主要是波形变换和整波,因为有电磁干扰或电路中有噪声的时候,那么经过GPIO管脚的电压就可能会不稳定,即上下起伏的;经过施密特触发器后,起伏的信号会被规整为矩形波,便于单片机识别高低电平信号
模拟模式
在模拟模式,单片机需要接收或发送模拟信号,因此电路中不需要任何去噪的电路,因此可以简单理解为就一条直线连接到单片机对应管脚。
这时,弱上拉和下拉电阻禁用;输出缓冲器禁用;施密特触发输入禁用;端口输入状态寄存器相应位为“0”。
浮空输入
当单片机管脚处于浮空输入,输入电路中的上拉和下拉电阻被禁用,施密特触发器使能,可以理解为管脚上为高或低电平,单片机就接收到高或低电平。
下拉输入
当单片机处于下拉输入,输入电路中的下拉电阻使能,施密特触发器使能。当管脚接上了线时,它的作用是和浮空输入一样的;但当管脚悬空时,管脚电平会被下拉至低电平,此时单片机只能接收到低电平。
上拉输入
当单片机处于上拉输入,输入电路中的上拉电阻使能,施密特触发器使能。现象和下拉输入是相反的,就是当管脚悬空时,管脚电平会被上拉至高电平,此时单片机只能接收到高电平。
推挽输出
统一禁用上拉和下拉电阻,使能施密特触发器,使能输出缓冲区。
当处于推挽模式时,输出控制寄存器设置为“0”时,相应引脚输出低电平;输出控制寄存器设置为“1”,相应引脚输出高电平。
开漏
当处于开漏模式时,输出控制寄存器设置为“0”时,相应引脚输出低电平;输出控制寄存器设置为“1”,相应管脚处于高阻状态。
低功耗配置方式
所有未使用的引脚都应配置为模拟输入,在这种情况下,施密特触发器被禁用,每个 I/O 零消耗,避免产生额外的电流。对于输出,推荐使用最低的 I / O 速度,若不必要时,用户应避免激活上拉、下拉配置。在不需要时,用户也需要禁用时钟输出引脚。
低功耗模式下,若 GPIO 有外部元件输入/输出,建议配置输入为上拉/下拉、输出推挽以保证 GPIO 空闲时为固定电平,通过上下拉在休眠前将GPIO配置为非使能的电平。
全部GPIO进入模拟模式可以达到接近官方低功耗电流
但由于需要烧录所以BOOT,swd不能配置成模拟模式,同时外部中断key_on和shutdown唤醒也不能进入模拟模式
测试
休眠能耗测试(RTC唤醒默认开启1HZ) | GD32工作模式 | GPIO配置 | 单片机加上外围电路的平均电流(电压/20欧电阻 = 电流) |
---|---|---|---|
正常上电 | run mode | 使用所有外设和时钟 | 76.844mv/20=3.84mA |
正常上电 | run mode | 禁用所有外设和时钟 | 64.2mV/20=3.21mA |
深度休眠测试 | Deep Sleep mode | 使用所有外设和时钟 | 69mV/20 = 3.45mA |
深度休眠测试 | Deep Sleep mode | 禁用所有外设和时钟 | 34mV/20=1.7mA |
深度休眠测试 | Deep Sleep mode | 将所有GPIO设置成模拟模式 | 1.105mV/20=55.20uA |
深度休眠1 | Deep Sleep1 mode | 使用所有外设和时钟 | 43mV/20= 2.15mA |
深度休眠1 | Deep Sleep1 mode | 禁用所有外设和时钟 | 34mV/20= 1.7mA |
深度休眠1 | Deep Sleep1 mode | 将所有GPIO设置成模拟模式 | 0.086mV/20= 4.3uA |
深度休眠1 | Deep Sleep1 mode | 将除SWD和BOOT的GPIO设置成模拟模式,并且禁用UART,ADC,DMA等外设(注意禁用需要开启对应的时钟) | 0.286mV/20= 14.3uA |
深度休眠2 | Deep Sleep2 mode | 使用所有外设和时钟 | 35mV/20= 1.75mA |
深度休眠2 | Deep Sleep2 mode | 禁用所有外设和时钟 | 25mv/20= 1.25mA |
深度休眠2 | Deep Sleep2 mode | 将所有gpio设置成模拟模式 | 2.9uA |
待机模式 | Standby mode | 禁用所有外设和时钟,并且将GPIO设置为模拟模式 | 2uA |