STM32L1XX系列低功耗

1电源管理

  • 上电复位 POR 参考

  • 掉电复位 PDR

  • 欠压复位
    使能BOR后POR和PDR的门限将被忽略,转而使用BOR设置的门限,BOR门限 在 option bytes中配置

模式 门限
1 1.8V上电 1.65V断电
2 2.1V上电 2.0V断电
3 2.4V上电 2.3V断电
4 2.7V上电 2.6V断电
5 2.9V上电 2.8V断电
  • 可编程电压监控 PVD

软件控制,监控VDD,门限可以设置在1.8-3.1间,100mV为间隔,当PVD大于或者小于门限则产生一个外部中断.

2低功耗模式

2.1低功耗运行模式

内核和外设都可以保存运行状态,需要配置内部电源变换器工作在低功耗模式下,系统时钟必须设置在128KHz一下,可以使用MSI作为系统时钟,内核供电必须选择供电范围2(1.5V),并且关闭动态电压调节功能

2.2睡眠模式

内核停止运行,外设保持运行.
通过特殊指令进入睡眠模式.
WFI由中断唤醒,任意的NVIC识别到外设中断都可以唤醒内核
WFE由事件唤醒,被配置为事件模式的EXTI中断唤醒内核

2.3低功耗睡眠模式

内核停止运行,外设保存运行

2.4停止模式

内核停止,内核电源范围内的时钟都停止,晶振也禁止,SRAM和寄存器内容保留。启动时需要重新配置时钟,并且清除标志位,唤醒后程序继续之前的运行。

2.5待机模式

电源内部变换器关闭、内核电源范围内全部断电,晶振被禁止,SRAM和寄存器不保留,RTC寄存器和备份寄存器保留。在待机模式下所有IO都保存高阻态,除了复位、RTC报警输出引脚、唤醒引脚,功耗典型值为1ua,但是如果对接了外部电路,不用配置引脚的优势也就变成了劣势,就如同我测试的SPI设备,待机模式的时候MOSI和SCK实际上是有电流的,功耗降不下去,这种时候选择停止模式,来单独配置IO口才行。

2.6 总结

image

3 代码与测试

测试硬件: 将STM32L151开发板上的多余器件全部去除
低功耗初始化函数

void low_power_init()
{
  /* Enable Ultra low power mode */
  HAL_PWREx_EnableUltraLowPower();
    
  /* Enable the fast wake up from Ultra low power mode */
  HAL_PWREx_EnableFastWakeUp();
    
    HAL_PWR_DisablePVD();
        
}

3.1待机模式(standby)

进入待机模式的代码,使用HAL库中的stm32l1xx_hal_pwr.c文件,下列中如果不进行清除标志位,则设备在第二次进入待机模式后将自动被唤醒。

void enter_standby_wakup()
{
        if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)
        {
            /* Clear Standby flag */
            __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB); 
        }
      HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
      __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
        
      HAL_PWR_EnterSTANDBYMode();
}

进入低功耗后所有引脚都会被置为高阻态,正常运行时功耗在10几mA,进入standby后电流下降到1~5uA左右,通过PA0上拉唤醒,该引脚也无需配置

3.2停止模式

代码使用了一个启动后常亮的引脚和一个外部中断按键,前者用于判断在进入停机模式后,引脚状态,结果是引脚仍然处于之前的状态,也就是寄存器被保持了。后者用于退出停机模式。

//该模式在退出时候必须重新配置时钟
//该模式需要在中断回调中添加
//__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

void enter_stop_exti()
{
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    SystemClock_Config();
}

如果单单进入停止模式,外部引脚是有可能消耗电量的,可用如下代码将全部引脚置为浮空输入,并且关闭GPIO时钟

  GPIO_InitTypeDef GPIO_InitStructure = {0};
  /* Enable GPIOs clock */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();

  /* Configure all GPIO port pins in Analog Input mode (floating input trigger OFF) */
  GPIO_InitStructure.Pin = GPIO_PIN_All;
  GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStructure.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 
  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
  HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);

  /* Disable GPIOs clock */
  __HAL_RCC_GPIOA_CLK_DISABLE();
  __HAL_RCC_GPIOB_CLK_DISABLE();
  __HAL_RCC_GPIOC_CLK_DISABLE();
  __HAL_RCC_GPIOD_CLK_DISABLE();
  __HAL_RCC_GPIOH_CLK_DISABLE();

但并不是所有引脚都应该配置成浮空输入,对于一些特殊引脚可用在关闭时钟前进行单独配置,例如

~~~
        GPIO_InitStructure.Pin = GPIO_PIN_7;
        GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD;
        GPIO_InitStructure.Pull = GPIO_PULLDOWN;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
~~~

停止模式并不会重启程序,被唤醒后将会继续执行之前的代码,也就是说引脚是应该被回复成被应用的状态,我们可以在将所有引脚配置成为浮空输入之前保存一下GPIO寄存器的值,然后在退出停止模式后,将保存的值再赋值给寄存器。

//读取当前GPIO状态
GPIO_TypeDef gpio_a;
GPIO_TypeDef gpio_b;
GPIO_TypeDef gpio_c;
GPIO_TypeDef gpio_h;
rt_memcpy(&gpio_a,GPIOA,sizeof(GPIO_TypeDef));
rt_memcpy(&gpio_b,GPIOB,sizeof(GPIO_TypeDef));
rt_memcpy(&gpio_c,GPIOC,sizeof(GPIO_TypeDef));
rt_memcpy(&gpio_h,GPIOH,sizeof(GPIO_TypeDef));

//复位IO
rt_memcpy(GPIOA,&gpio_a,sizeof(GPIO_TypeDef));
rt_memcpy(GPIOB,&gpio_b,sizeof(GPIO_TypeDef));
rt_memcpy(GPIOC,&gpio_c,sizeof(GPIO_TypeDef));
rt_memcpy(GPIOH,&gpio_h,sizeof(GPIO_TypeDef));

3.3 睡眠模式

睡眠模式能够被任意中断唤醒,也就是滴答定时器中断也能唤醒它,下列示例代码是在rtt系统下,在空闲回调里面添加进入休眠模式

void enter_sleep()
{
    /*Suspend Tick increment to prevent wakeup by Systick interrupt. 
    Otherwise the Systick interrupt will wake up the device within 1ms (HAL time base)*/
    //HAL_SuspendTick();

    /* Enter Sleep Mode , wake up is done once Key push button is pressed */
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);

    /* Resume Tick interrupt if disabled prior to sleep mode entry*/
    //HAL_ResumeTick();
}

void low_pwoer_hook_cb()
{
     //该回调未关闭滴答
   enter_sleep();
}

void low_power_set_idle_hook()
{
        rt_thread_idle_sethook(low_pwoer_hook_cb);
}

4 官方文档翻译

  • 芯片功耗典型值
    待机模式:0.28uA
    待机模式+RTC:1.11uA
    停止模式:0.44uA
    停止模式+RTC:1.38uA
    低功耗运行模式:10.9uA
    运行模式: 185uA/MHz

5 实际测试图

下图为STM32L151进入停止模式 和 SX1278进入休眠模式的功耗图


image.png

你可能感兴趣的:(STM32L1XX系列低功耗)