STM32L0系列的低功耗模式

介绍

意法半导体的超低功耗MCU系列采用低泄漏技术和优化设计,实现了极低的电流消耗,使其成为电池供电和能量收集应用的理想选择。为了充分利用这些器件的低功耗特性,必须了解可用的低功耗模式、如何配置它们以及它们最适合哪些任务。本文概述了STM32L053C8 MCU的低功耗模式。然而,任何STM32L0器件都可以作为示例,因为整个系列的低功耗模式是相同的。超低功耗系列还包括STM32L1系列和STM32L4系列。这些器件具有更高的性能,配备了更先进的内核、更大的存储容量和更丰富的外设。它们具有与L0系列相同的低功耗模式(L4系列还额外增加了一些功能),因此本文也是了解它们的良好起点。图1摘自意法半导体的一份宣传册,简明扼要地总结了L0、L1和L4系列的特点和优势。


1 :STM32超低功耗产品系列对比

在使用意法半导体的MCU进行任何工作时,有两份文档应随时备查。第一份是参考手册,对于STM32L053C8而言,即STM32L0x3参考手册。该文档包含有关STM32L0x3系列的详细信息,例如如何使用存储器和外设。对于产品线中特定器件的更详细信息,如引脚映射、电气特性和封装信息,应参考数据手册(此处为STM32L053xx数据手册)。就低功耗模式而言,参考手册将详细说明如何进入和退出这些模式,而数据手册将具体定义外设可用性、可能的唤醒源和电流消耗估算。

背景

STM32L0基于Cortex-M0+内核构建,这意味着其低功耗能力取决于该内核的电源管理特性。这些特性可以通过系统控制块中的系统控制寄存器(SCR)进行配置。遗憾的是,参考手册和数据手册均未记录内核寄存器。意法半导体为需要Cortex-M0+简明文档的用户提供了STM32L0系列Cortex-M0+编程手册。有关Cortex-M0、M0+和M1内核的完整文档可在ARMv6-M架构参考手册中找到。这两份文档都包含有关 电源管理 的章节,是了解该主题的良好起点。


2 :SCR寄存器位

如图2所示,SCR由三个位组成:SEVONPEND、SLEEPONEXIT和SLEEPDEEP。SEVONPEND(Send EVent ON PENDing)位允许进入挂起状态的中断触发唤醒事件。请注意,如果这些中断未在NVIC中启用,仍会产生唤醒事件,但不会进入中断服务程序(ISR)。有关挂起中断、启用中断或NVIC的更多信息,请参阅前述 Cortex-M0+ 手册中关于嵌套向量中断控制器 的章节。SLEEPONEXIT位提供了在异常返回后、程序恢复执行前将处理器置于低功耗模式的选项。这对于仅需在服务中断时保持唤醒的应用非常理想。最后,SLEEPDEEP位允许进入深度睡眠状态,而非常规睡眠状态。采用Cortex-M0+内核的芯片制造商会决定设备在这些状态下的具体行为。以ST为例,睡眠状态用作睡眠模式和低功耗睡眠模式的基础,而深度睡眠状态则用作停止模式和待机模式的基础。

Cortex-M0+有三种进入低功耗模式的方式。第一种是使用WFI(等待中断)指令。顾名思义,若设备因该指令进入低功耗模式,则NVIC中启用的中断可唤醒设备。第二种方式是通过执行WFE(等待事件)指令进入低功耗模式。这与WFI指令非常相似,但提供了更大的灵活性。设备不仅可由扩展中断和事件控制器(EXTI)配置的事件唤醒,还能被NVIC中禁用(但在对应外设控制寄存器中启用)的中断唤醒。第三种进入低功耗模式的方式前文已提及。通过在SCR中设置SLEEPONEXIT位,异常返回将使设备进入低功耗模式,效果等同于执行了WFI指令。请注意,在所有这些情况下,仅当没有中断或事件挂起时才会进入低功耗模式。由于WFI和WFE不能保证暂停程序执行,它们常被称为"提示指令"。

最后值得提及的核心寄存器是PRIMASK寄存器。它仅包含一个可配置位PM(可优先中断屏蔽位),若设为’1’将禁用所有具有可配置优先级的中断。这不仅可用于执行原子操作,还能在系统需要先恢复至工作状态时延迟ISR的执行。关于此的示例将在详细介绍停止模式的章节中提供。

为便于开发C应用程序时访问WFI和WFE指令,CMSIS-CORE标准提供了__WFI()__WFE()函数。后续章节的所有示例函数都使用__WFI()来执行WFI指令并进入低功耗模式。此外,CMSIS并未直接提供对PRIMASK寄存器的访问,而是通过__disable_irq()__enable_irq()函数分别设置和清除PM位。要检查PM位的状态,__get_PRIMASK()函数将返回其当前值。大多数集成开发环境(IDE)都能非常简便地将CMSIS驱动程序添加到项目中。例如在Keil中,确保通过Pack Installer安装了ARM::CMSIS,并在创建新项目时于运行时环境管理器中勾选CMSIS组件下的"CORE"包即可。

低功耗模式

STM32L0系列器件实现了五种低功耗模式:低功耗运行模式、睡眠模式、低功耗睡眠模式、停止模式和待机模式。这些模式的区别可通过功耗、性能、唤醒时间和唤醒源等方面来描述。若将每种模式的各项参数按最优(1)至最差(5)排序,就能清晰看出其权衡取舍。一般而言,随着功耗降低,性能会减弱,唤醒时间延长,可用唤醒源数量也会减少。表1总结了各低功耗模式的排序情况。以低功耗运行模式为例进行解读。该模式具有最佳性能、最多唤醒源、第二快的唤醒时间,以及第四低的电流消耗。

1 :基于不同运行参数的STM32L0低功耗模式序数排名

低功耗运行 睡眠 低功耗睡眠 停止 待机
性能 1 2 3 4 5
功耗 4 5 3 2 1
唤醒时间 2 1 4 3 5
唤醒源 1 2 3 4 5

本节内容将阐明这些排名的推导依据。但需要提前明确的是,这些结论仅适用于普遍情况。例如根据配置和启用/禁用的外设情况,停止模式的电流消耗完全可能高于低功耗睡眠模式。但通常不会出现这种情况,因为停止模式为节省更多功耗,对器件功能的限制远甚于低功耗睡眠模式。

虽然本文未提供各模式下的具体电流值,但《STM32L053探索板IDD电流测量功能使用指南》页面给出了各低功耗模式的实测示例。

低功耗运行模式

将其宣传为低功耗模式颇具欺骗性,因为它节能的主要方式是要求系统时钟频率处于低位。将任何微控制器的时钟速度降至千赫兹范围,都会显著降低电流消耗,使其足以与普通睡眠模式媲美。但通常不这么做,是因为性能下降加上静态电流消耗(与时钟频率无关)长期来看可能消耗更多能量。根据应用场景(即使用哪种睡眠模式或设备唤醒频率),短时间内消耗更多电流可能比长时间消耗较少电流更高效。ST能将此归类为低功耗模式,是因为他们提供了将内部稳压器切换至低功耗状态的功能。这会降低设备的静态电流消耗,从而最小化其在性能与总电流消耗之间的权衡影响。

要将稳压器切换至低功耗模式,必须满足两个条件。第一,稳压器电压(VCORE)必须处于范围2。幸运的是,根据PWR_CR寄存器文档,这是稳压器的默认配置。因此,除非利用了设备的动态电压调节功能,否则无需担心此前提条件。第二条件是系统频率不得超过fMSI范围1。根据MSIRANGE位(位于RCC_ICSCR寄存器)的描述,这对应约131.072 kHz的频率。在此速度和功率水平下,USB、ADC和TSC(触摸感应控制器)外设不可用。任何频率相关外设(USART、定时器等)若曾在运行模式下初始化,则系统频率变更后需重新初始化才能继续正常工作。

与其他低功耗模式不同,低功耗运行模式下CPU不会停止工作。这意味着它不是通过WFI/WFE指令进入(如前所述),而是通过设置PWR_CR寄存器中的LPSDSR(低功耗睡眠/深度睡眠/低功耗运行)和LPRUN(低功耗运行)位实现。注意:必须先设置LPSDSR再设置LPRUN;必须先清除LPRUN再清除LPSDSR;且进入其他低功耗模式前应清除LPRUN。由于程序在低功耗运行模式下持续执行,设备通过软件"唤醒",而非受限于有限的中断或事件集合。只需清除LPRUN位并将系统频率恢复至全速,即可让系统返回运行模式。清单1展示了根据参考手册步骤进入低功耗运行模式的完整流程。清单2演示了当设备无需保持低功耗运行模式时如何重新进入运行模式。

清单 1 :进入低功耗运行模式示例

void enter_LPRun( void )
{
    /* 1. Each digital IP clock must be enabled or disabled by using the
                   RCC_APBxENR and RCC_AHBENR registers */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    /* 2. The frequency of the system clock must be decreased to not exceed the
          frequency of f_MSI range1. */
    Config_SysClk_MSI_131();
    // Reinitialize peripherals dependent on clock speed
    USART1_Init();
    SysTick_Init( 0.001 );
    I2C1_Init();
    /* 3. The regulator is forced in low-power mode by software
          (LPRUN and LPSDSR bits set ) */
    PWR->CR &= ~PWR_CR_LPRUN; // Be sure LPRUN is cleared!
     
    PWR->CR |= PWR_CR_LPSDSR; // must be set before LPRUN
    PWR->CR |= PWR_CR_LPRUN; // enter low power run mode
}

清单 2 :进入运行模式示例

void enter_Run( void )
{
    /* Enable Clocks */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
 
    /* Force the regulator into main mode */
    // Reset LPRUN bit
    PWR->CR &= ~( PWR_CR_LPRUN );
    // LPSDSR can be reset only when LPRUN bit = 0;
    PWR->CR &= ~( PWR_CR_LPSDSR );
    /* Set HSI16 oscillator as system clock */
    Config_SysClk_HSI16();
    // Reinitialize peripherals dependent on clock speed
    USART1_Init();
    SysTick_Init( 0.001 );
    I2C1_Init();
}

睡眠模式

在低功耗模式中,睡眠模式最为直接,它以消耗更多功率为代价,提供最短的唤醒时间。数据手册指出,在所有外设禁用且系统频率为16 MHz时,约消耗1 mA电流。这远高于其他低功耗模式,后者可实现微安甚至纳安级别的功耗。然而,其唤醒速度比最具竞争力的低功耗模式快近十倍。表2显示了设备从各低功耗模式唤醒并进入运行模式所需的时间。唤醒时间数值取自数据手册的表4。

2 :各低功耗模式唤醒至运行模式的时间

低功耗模式 唤醒时间
低功耗运行 3微秒
睡眠 0.36微秒
低功耗睡眠 32微秒
停止 3.5微秒
待机 50微秒

睡眠模式下,仅内核停止运行,所有外设仍保持工作。这使得进入睡眠模式几乎毫不费力,因为无需降低系统频率,且设备所有外设均可正常使用。此外,退出睡眠模式也非常简单,任何运行模式下的中断或事件都能以极低延迟唤醒设备并得到处理。因此,睡眠模式几乎适用于CPU空转等待事件发生的所有场景。用户无需进入忙等待循环,只需执行WFI或WFE指令(取决于唤醒方式)即可暂停执行并节省功耗,直到再次需要内核。这是因为系统控制寄存器默认配置为睡眠模式,即SLEEPDEEP位被清零。对于仅需通过中断服务来唤醒CPU的应用场景,设置SLEEPONEXIT位并在中断服务完成后始终进入睡眠模式,比恢复程序执行更为合理。

代码清单3展示了进入睡眠模式的函数示例。由于该函数取自使用多种低功耗模式的程序,首条语句会清除SLEEPDEEP位以避免意外行为。同时,为消除唤醒延迟,闪存访问控制寄存器被配置为在设备睡眠期间保持非易失性存储器处于空闲状态。关闭闪存接口时钟的详细讨论见低功耗睡眠模式章节。

代码清单 3 :进入睡眠模式示例

void enter_Sleep( void )
{
    /* Configure low-power mode */
    SCB->SCR &= ~( SCB_SCR_SLEEPDEEP_Msk );  // low-power mode = sleep mode
    SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;     // reenter low-power mode after ISR
     
    /* Ensure Flash memory stays on */
    FLASH->ACR &= ~FLASH_ACR_SLEEP_PD;
    __WFI();  // enter low-power mode
}

低功耗睡眠模式

低功耗睡眠模式本质上是低功耗运行模式与睡眠模式的结合。不仅Cortex-M0+内核会停止运行,稳压器也会进入低功耗状态,这意味着必须满足与低功耗运行模式相同的条件。需注意VCORE必须保持在范围2(默认配置),且系统时钟频率需降至不超过 fMSI范围1(131.072 kHz)。因此,USB、ADC和TSC外设在此模式下不可用。此外,任何在低功耗睡眠模式下继续运行的频率相关外设都需要重新初始化以确保正常工作。

与低功耗运行模式不同,LPRUN位不用于将稳压器切换至低功耗状态。降低系统频率后,应设置LPSDSR位并遵循相同的睡眠模式进入流程。即:确保清除SLEEPDEEP位,执行WFI/WFE指令,或设置SLEEPONEXIT位等待异常返回。当设备进入低功耗模式时,LPSDSR位将自动使稳压器转入低功耗状态。设备因唤醒事件退出低功耗模式后,将进入稳压器全功率运行的常规模式。

参考手册在低功耗睡眠模式章节提及了关闭闪存的选项。设置FLASH_ACR寄存器中的SLEEP_PD(睡眠掉电)位后,设备进入睡眠模式或低功耗睡眠模式时,非易失性存储器将进入掉电状态。虽然这会增加唤醒延迟,但功耗可降低约12µA(数据手册表34),具体价值取决于应用需求。参考手册未在睡眠模式章节提及此选项(尽管该功能在睡眠模式下有效),推测是由于唤醒时间延长所致。若应用场景无需睡眠模式提供的极速唤醒,则应优先考虑使用低功耗睡眠模式。代码清单4展示了根据参考手册流程进入低功耗睡眠模式的函数示例。

代码清单 4 :进入低功耗睡眠模式示例

void enter_LPSleep( void )
{
    /* 1. The Flash memory can be switched off by using the control bits
              (SLEEP_PD in the FLASH_ACR register). This reduces power consumption
              but increases the wake-up time. */
    FLASH->ACR |= FLASH_ACR_SLEEP_PD;
    /* 2. Each digital IP clock must be enabled or disabled by using the
                RCC_APBxENR and RCC_AHBENR registers */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    /* 3. The frequency of the system clock must be decreased to not exceed the
                frequency of f_MSI range1. */
    // Set MSI 131.072 kHz as system clock
    Config_SysClk_MSI_131();
    // Reinitialize peripherals dependent on clock speed
    USART1_Init();
    SysTick_Init( 0.001 );
    I2C1_Init();
    /* 4. The regulator is forced in low-power mode by software
                (LPSDSR bits set ) */
    PWR->CR |= PWR_CR_LPSDSR; // voltage regulator in low-power mode during sleep
    /* 5. Follow the steps described in Section 6.3.5: Entering low-power mode */
    SCB->SCR &= ~( SCB_SCR_SLEEPDEEP_Msk ); // low-power mode = sleep mode
    SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; // reenter low-power mode after ISR
    __WFI(); // enter low-power mode
}

停止模式

可以说,停止模式是STM32L0系列中最复杂的低功耗模式,它能在保持SRAM和寄存器内容的同时,将电流消耗降至纳安级别。然而,若唤醒时间更为关键,则可以忽略许多节能选项,以实现与低功耗运行模式相当的延迟。更复杂的是,可用的唤醒源数量有限,勘误表中多次提及停止模式,且调试复杂度增加。尽管如此,对于希望在唤醒时无需重新初始化系统且功耗最低的应用,停止模式仍是最佳选择。

在停止模式下,内核停止运行,唯一能工作的振荡器是LSE、LSI以及有限功能的HSI。低速时钟使RTC和IWDG得以持续运行并唤醒设备。HSI可为能在停止模式下运行的外设提供有限功能。例如,USART和I2C在停止模式下仍能通过按需唤醒HSI来接收数据。HSI仅会为请求它的外设供电,并在不再需要时自动关闭。有关停止模式下所有可用外设及唤醒源的完整列表,请参见数据手册中的表4。需注意,由于内核时钟停止,进入停止模式后将无法维持调试连接。但参考手册指出,设置DBGMCU_CR寄存器中的DBG_STOP位可实现在停止模式下调试。

要进入停止模式,必须设置SLEEPDEEP位,因为停止模式和待机模式都是Cortex-M0+内核提供的深度睡眠状态实现。清除PWR_CR寄存器中的PDDS(Power Down DeepSleep)位可选择停止模式而非待机模式。此外,还需确保PWR_CSR寄存器中的WUF(唤醒标志)位被清除。遗憾的是,该位无法通过软件修改,必须通过向PWR_CR寄存器的CWUF(清除唤醒标志)位写入’1’来清除。此操作将在2个系统时钟周期后清除WUF。满足上述条件后,用户只需执行WFI指令、WFE指令,或设置SLEEPONEXIT位并等待异常返回。请注意,默认情况下,设备从停止模式唤醒时会选择MSI振荡器作为系统时钟。若在进入停止模式前设置RCC_CFGR寄存器中的STOPWUCK(停止模式唤醒时钟)位,系统时钟将改为选择HSI16振荡器。清单5展示了一个使用此最低配置进入停止模式的示例函数。该示例还演示了如何启用能唤醒设备的外部中断。

清单 5 :进入停止模式的简单示例

void enter_Stop( void )
{   
    /* Enable Clocks */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
     
    /* Configure PA0 as External Interrupt */
    GPIOA->MODER &= ~( GPIO_MODER_MODE0 ); // PA0 is in Input mode
    EXTI->IMR |= EXTI_IMR_IM0; // interrupt request from line 0 not masked
    EXTI->RTSR |= EXTI_RTSR_TR0; // rising trigger enabled for input line 0
     
    // Enable interrupt in the NVIC
    NVIC_EnableIRQ( EXTI0_1_IRQn );
    NVIC_SetPriority( EXTI0_1_IRQn, BTN_INT_PRIO );
     
    /* Prepare to enter stop mode */
    PWR->CR |= PWR_CR_CWUF; // clear the WUF flag after 2 clock cycles
    PWR->CR &= ~( PWR_CR_PDDS ); // Enter stop mode when the CPU enters deepsleep
    RCC->CFGR |= RCC_CFGR_STOPWUCK; // HSI16 oscillator is wake-up from stop clock
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // low-power mode = stop mode
    __WFI(); // enter low-power mode
}

若需进一步节能且对唤醒时间要求不高,可在进入停止模式前进行更多配置。最简单的方法是通过设置PWR_CR寄存器中的LPSDSR位,将稳压器切换至低功耗模式。在同一寄存器中,若模拟外设未使用VREFINT(内部电压基准),也可设置ULP(超低功耗模式)位来禁用它。此外,若唤醒后无需立即使用VREFINT,设置FWU(快速唤醒)位可避免因设置ULP而产生的额外唤醒延迟。

上述改动将显著降低电流消耗,但器件仍可能维持微安级电流。要达到纳安级功耗范围,需将所有GPIO引脚切换至模拟模式。参考手册第9.3.12节指出,当I/O引脚配置为模拟模式时,施密特触发器输入被禁用,使每个引脚实现零功耗。但此操作需在切换引脚模式前,保存各端口GPIOx_MODER寄存器的原始状态。这样器件唤醒时,所有引脚均可立即恢复至先前工作模式。同时为避免意外错误,保存与恢复过程中应禁用中断。

清单6所示函数基于清单5的基础函数构建。该函数不仅将稳压器设为低功耗模式并关闭VREFINT,还在进入停止模式前保存了I/O上下文。由于执行WFI指令时(即PM位置位)中断被禁用,外部中断虽能唤醒器件但不会进入其ISR。程序会直接从WFI指令处继续执行,使得上下文得以立即恢复。重新启用中断后,因中断仍处于挂起状态,将进入外部中断的ISR。

清单 6 :进入停止模式的高级示例

void enter_Stop( void )
{   
    /* Enable Clocks */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    RCC->IOPENR |= RCC_IOPENR_GPIOAEN;
     
    /* Configure PA0 as External Interrupt */
    GPIOA->MODER &= ~( GPIO_MODER_MODE0 ); // PA0 is in Input mode
    EXTI->IMR |= EXTI_IMR_IM0;   // interrupt request from line 0 not masked
    EXTI->RTSR |= EXTI_RTSR_TR0; // rising trigger enabled for input line 0
     
    // Enable interrupt in the NVIC
    NVIC_EnableIRQ( EXTI0_1_IRQn );
    NVIC_SetPriority( EXTI0_1_IRQn, BTN_INT_PRIO );
     
    /* Prepare to enter stop mode */
    PWR->CR |= PWR_CR_CWUF;      // clear the WUF flag after 2 clock cycles
    PWR->CR &= ~( PWR_CR_PDDS ); // Enter stop mode when the CPU enters deepsleep
    // V_REFINT startup time ignored | V_REFINT off in LP mode | regulator in LP mode
    PWR->CR |= PWR_CR_FWU | PWR_CR_ULP | PWR_CR_LPSDSR;
    RCC->CFGR |= RCC_CFGR_STOPWUCK; // HSI16 oscillator is wake-up from stop clock
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // low-power mode = stop mode
     
    __disable_irq();
     
    Idd_SaveContext();
    I2C1->CR1 &= ~I2C_CR1_PE;  // Address issue 2.5.1 in Errata
    __WFI(); // enter low-power mode
     
    I2C1->CR1 |= I2C_CR1_PE;
    Idd_RestoreContext();
     
    __enable_irq(); // <-- go to isr
}

清单5和6均使用PA0引脚的外部中断唤醒器件。这是因为外部中断由EXTI控制,除系统复位外,只有它能触发器件退出停止模式。简言之,EXTI管理着30条可生成中断和事件的内部/外部线路。参考手册表52详述了每条线路的信号源及其是否可配置。前例中EXTI线路0默认映射PA0,故无需单独配置该线路。仅需启用线路中断源、选择触发方式,并在NVIC中使能对应中断。若使用WFE指令进入停止模式,则需在事件模式下启用该线路。

表3总结了STM32L053x6/8勘误表中记录的停止模式限制。显然无论使用哪个芯片版本,程序员都需处理这些问题以避免意外错误。清单6函数实现了针对I2C外设未配置唤醒导致的建议解决方案。勘误表第2.5.1节说明:进入停止模式前禁用I2C外设,唤醒后立即重新启用,可避免错误发生。幸运的是,该解决方案可在保存和恢复I/O上下文的同时实施。

3 STM32 L053x6/8勘误表中记录的停止模式限制

章节 问题 修订版 A 修订版 Z 修订版 Y 修订版 X
章节2.1.2 当HSI16为系统时钟且被选为唤醒时钟时,无法通过复位事件退出停止模式 提供解决方案 已修复 已修复 已修复
章节2.1.10 从停止或睡眠模式唤醒时,若闪存处于掉电模式则存在唤醒问题 提供解决方案 提供解决方案 已修复 已修复
章节2.1.11 从停止模式唤醒时,若稳压器处于低功耗模式会导致意外系统复位 提供解决方案 提供解决方案 已修复 已修复
章节 2.1.12 I2C和USART无法将设备从停止模式唤醒 无可用解决方案 无可用解决方案 无可用解决方案 已修复
章节 2.5.1 当I2C外设中禁用从停止模式唤醒时,停止模式下会出现错误行为 提供解决方案 提供解决方案 提供解决方案 提供解决方案

待机模式

与停止模式不同,进入待机模式相当简单,因为用户的选择较少。唯一可用的振荡器是LSI和LSE,唯一能工作的外设是RTC和IWDG,电压调节器完全关闭,所有I/O引脚设置为高阻抗(因此保存上下文毫无意义)。用户只需设置SLEEPDEEP位、设置PDDS位,并通过向CWUF位写入‘1’确保WFU位被清除,即可进入待机模式。然后,执行WFI指令、WFE指令或在异常返回前设置SLEEPONEXIT,将使设备进入这种低功耗模式。退出待机模式的选择也较少。只有唤醒引脚(PA0或PC13)上的上升沿、RTC唤醒事件之一或IWDG复位才能唤醒设备。必须在进入待机模式前配置所选方法并清除相应的唤醒标志。请注意,STM32L053C8芯片只有两个唤醒引脚,而参考手册和数据手册通常会提到第三个唤醒引脚,该引脚仅在引脚数较多的封装中可用。

待机模式的最大问题是它不保存SRAM或寄存器的内容(RTC寄存器、RTC备份寄存器和待机电路除外)。从待机模式唤醒后,程序执行会以与发生复位相同的方式重新开始。为了确定系统是否从待机模式唤醒,可以在进入main()函数后立即检查PWR_CSR寄存器中的SBF(StandBy Flag)位。若该位被置位,则表明设备先前处于待机模式,此时应设置CSBF(清除待机标志位)以清除SBF。用户由此可判断系统应进行首次运行初始化,还是应恢复至先前状态。

注意表2中待机模式的唤醒时间最长。该预估时间不包含系统重新初始化及恢复程序执行所需时长。这种额外延迟不仅使得对唤醒事件的即时响应近乎不可能,还会严重限制待机模式的节能能力。为使平均电流消耗低于停止模式,设备需维持极长时间的待机状态。具体时长取决于唤醒/重新初始化过程中的电流消耗量。清单7展示了一个示例函数,可用于进入待机模式,且任意唤醒引脚均可唤醒设备。

清单 7 :进入待机模式示例

void enter_Standby( void )
{
    /* Enable Clocks */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
     
    /* Prepare for Standby */
    // if WKUP pins are already high, the WUF bit will be set
    PWR->CSR |= PWR_CSR_EWUP1 | PWR_CSR_EWUP2;
     
    PWR->CR |= PWR_CR_CWUF; // clear the WUF flag after 2 clock cycles
    PWR->CR |= PWR_CR_ULP;   // V_{REFINT} is off in low-power mode
    PWR->CR |= PWR_CR_PDDS; // Enter Standby mode when the CPU enters deepsleep
     
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // low-power mode = stop mode
    SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk; // reenter low-power mode after ISR
    __WFI(); // enter low-power mode
}

结论

针对燃气/水表、可穿戴设备或物联网传感器等超低功耗应用,STM32L系列微控制器提供多种低功耗模式,使用户能精准平衡性能与功耗。特别是STM32L0系列,采用能效最高的ARM处理器(Cortex-M0+),并提供五种低功耗模式以满足大多数入门级应用需求。结合低功耗外设使用可显著延长电池寿命,降低能量收集需求。

低功耗运行模式在保持最佳性能的同时,其电流消耗仍低于睡眠模式。由于CPU持续运行,设备唤醒决策由软件作出,在这方面提供了最大灵活性。但稳压器处于低功耗模式会引入过长的唤醒延迟,难以满足多数实时应用需求。这正是睡眠模式的优势所在,其唤醒时间仅0.36微秒,因内核停用时所有外设仍全速运行。但这也使其成为功耗最高的低功耗模式,外设性能和全套硬件唤醒源对此几无补偿。低功耗睡眠模式采用与低功耗运行模式相同的方法,将电流消耗降至与停止模式相当的水平,且不限制唤醒源数量。若仅需EXIT唤醒设备,停止模式在保持SRAM和寄存器内容的同时,可提供最低电流消耗。其唤醒时间与低功耗运行模式相当。最后,对于MCU长期闲置的应用,待机模式可能更为适合。该模式以极少的唤醒源和最长的唤醒时间为代价,实现了最低功耗。

要查看上述示例函数在实际应用中的使用,请访问:STM32L053探索板上使用IDD电流测量功能。该应用允许用户进入目标低功耗模式,查看该状态下的电流消耗。完整代码已提供,包含上述示例所用函数,如Config_SysClk_HSI16()Idd_SaveContext()等。此外,该页面的表1总结了使用这些功能进入各模式时的平均电流消耗。