GD32实战18__低功耗

为什么需要低功耗

​ 很多人都会陷入这样的误区,不用电池供电不需要低功耗。乍看之下似乎挺合理的,其实不然。低功耗并不是因为电源供电能力有限而做的不得已的选择,而是为了整个产品的长期稳定运作而做出的努力。

​ 我认为,每个系统都应该考量低功耗的设计。

实现低功耗

​ 本文只从芯片角度阐述低功耗,外围电路不做探讨。

​ 我们知道芯片本质上就是一堆门电路,每个门的开关都会伴随电流产生功耗,因此降低功耗最好的办法就是停止这些门电路的运作。故要断其源头,即关闭时钟和关闭电源。例如GD32.

  1. 我们可以是通过减缓系统时钟或者关闭未使用的外设或模块的时钟达到降低功耗的目的。
  2. 也可以通过控制电源域供电,达到低功耗目的,为此GD32支持3种省电模式。即,睡眠模式、深度睡眠模式和待机模式,如下表,在这里插入图片描述
  3. 各模式下的功耗,如下表,在这里插入图片描述
睡眠模式

该模式同M3的SLEEPING模式对应,该模式下仅官方M3的时钟。

进入方法是,

  1. 清除M3系统控制寄存器中的SLEEPDEEP位,执行WFI或WFE指令进入。

唤醒方法是,

  1. WFI指令,任何中断都可以唤醒。
  2. WFE指令,任何事件都可以唤醒。

进入机制是,根据M3的SCR(系统控制寄存器)的SLEEPONEXIT位,支持两种睡眠进入机制,

  1. sleep-now:如果SLEEPONEXIT位被清零,一旦执行WFI或WFE指令,MCU立即进入睡眠模式。
  2. sleep-on-exit:如果SLEEPONEXIT位被置位,当系统从最低优先级的中断处理程序离开后,MCU立即进入睡眠模式。

特点是,唤醒时间最短。

代码如下,

void PWR_SLEEPMode_Entry(uint8_t PWR_SLEEPENTRY)
{
    /* Clear SLEEPDEEP bit of Cortex-M3 System Control Register */
    SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
    
    /* Select WFI or WFE to enter Sleep mode */
    if(PWR_SLEEPENTRY == PWR_SLEEPENTRY_WFI)
    {
        __WFI();
    }
    else
    {
        __WFE();
    }
}
深度睡眠模式

该模式同M3的SLEEPDEEP模式对应,该模式下,1.2V域中所有时钟全部关闭,HSI,HSE、及PLL也全部被禁用。

进入方法是,

  1. 将M3系统控制寄存器SLEEPDEEP位置1
  2. 清除PWR_CTLR寄存器的SDBM位
  3. 执行WFI或WFE指令立即进入

唤醒方法是,任何来自EXTI的中断或唤醒事件都可以唤醒。

特点及注意事项,

  1. 刚退出深度睡眠模式时,会选HSI作为系统时钟。
  2. 为了顺利进入深度睡眠模式,所有EXTI线上的挂起状态(在EXTI_PD寄存器中)和RTC闹钟标志必须复位,否则,无法进入深度睡眠模式。
  3. LDO从低功耗模式唤醒,需要延时等待。
  4. 保留寄存器和SRAM中的数据。

LDO低功耗,

  1. 可以通过PWR_CTLR寄存器中的LDOLP位控制LDO工作在正常模式还是低功耗模式。
  2. LDO从低功耗模式唤醒,需要延时等待。
void PWR_DEEPSLEEPMode_Entry(uint32_t PWR_LDO, uint8_t PWR_DEEPSLEEPENTRY)
{ 
    uint32_t temp = 0;
    
    /* Select the LDO state in Deep-sleep mode */
    temp = PWR->CTLR;
    
    /* Clear SDBM and LDOLP bits, and select Deep-sleep mode */
    temp &= ~((uint32_t)(PWR_CTLR_SDBM | PWR_CTLR_LDOLP));
    
    /* Set LDOLP bit according to PWR_LDO value, and select the LDO's state */
    temp |= PWR_LDO;
    
    /* Store the new value */
    PWR->CTLR = temp;
    
    /* Set SLEEPDEEP bit of Cortex-M3 System Control Register */
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
    
    /* Select WFI or WFE to enter Deep-sleep mode */
    if(PWR_DEEPSLEEPENTRY == PWR_DEEPSLEEPENTRY_WFI)
    {
        __WFI();
    }
    else
    {
        __SEV();
        __WFE();
        __WFE();
    }
    /* Reset SLEEPDEEP bit of Cortex-M3 System Control Register */
    SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
}
待机模式

该模式可以看做是SLEEPDEEP模式的升级版,把1.2V域全部断电,LDO,HSI,HSE,PLL也断电。

进入方法是,

  1. 将M3系统控制寄存器的SLEEPDEEP位置1,
  2. PWR_CTLR寄存器的SDBM位置1,
  3. 清除PWR_STR寄存器的WUF位,
  4. 执行WFI或WFE指令立即进入。

检查方法是,可以通过PWR_STR寄存器中的SBF位状态判断MCU是否进入待机模式。

唤醒方法是,只有下面4种

  1. NRST引脚的外部复位
  2. RTC报警
  3. IWDG复位
  4. WKUP引脚上升沿

特点是,

  1. 功耗最低,唤醒时间最长
  2. SRAM和寄存器的内容丢失,备份寄存器除外
  3. 退出待机模式时,会发生上电复位
void PWR_STDBYMode_Entry(uint8_t PWR_STDBYENTRY)
{
    /* Set SLEEPDEEP bit of Cortex-M3 System Control Register */
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

    /* Set SDBM bit, and select Standby mode */
    PWR->CTLR |= PWR_CTLR_SDBM;
        
    /* Reset Wakeup flag */
    PWR->CTLR |= PWR_CTLR_WUFR;
    
    /* Select WFI or WFE to enter Standby mode */
    if(PWR_STDBYENTRY == PWR_STDBYENTRY_WFI)
    {
        __WFI();
    }
    else
    {
        __WFE();
    }
}
  • 10
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值