STM32 使用 STM32CubeMX HAL库实现低功耗模式

STM32  使用 HAL 库的低功耗模式测试使用   ...... 矜辰所致

前言

上次画了一个 STM32L010F4 最小系统的板子,也做了一些基本测试,但是最重要的低功耗一直拖到现在,以前在使用 STM32L151 的时候用标准库做过低功耗的项目,现在都使用 STM32CubeMX 了,一直都未使用过。

那正好借着这次机会来记录一下,所以本文内容就是测试下在 STM32CubeMX 环境下如何实现 STM32 的低功耗模式。

以前 STM32L151 标准库低功耗文章:
STM32L151低功耗项目笔记(CO传感器TGS5042)
.
本次使用的测试芯片为 STM32L010F4 :
STM32L010F4 最小系统设计
.
我是矜辰所致,全网同名,尽量用心写好每一系列文章,不浮夸,不将就,认真对待学知识的我们,矜辰所致,金石为开!

目录

  • 前言
  • 一、 STM32 低功耗模式
  • 二、 HAL 库休眠测试
    • 2.1 HAL 低功耗相关函数
    • 2.2 使用测试
      • 2.2.1 Sleep Mode 测试
      • 2.2.2 Stop Mode 按键唤醒
      • 2.2.3 Stop Mode RTC唤醒
        • 修改 RTC 唤醒周期
      • 2.2.4 Standby Mode 测试
        • 细节问题之如何节约内存空间
  • 三、 关于低功耗的其他细节说明
    • 3.1 `PWR_FLAG_WU` 和 `PWR_FLAG_SB`
    • 3.2 低功耗模式下的烧录问题
    • 3.3 休眠模式下的 IO 口问题
    • 3.4 关于 MCU 的时钟
  • 结语

一、 STM32 低功耗模式

关于 STM32 的低功耗模式,这个网络的文章一大堆,但是总的来说低功耗模式分为下面三类:

睡眠模式(Sleep Mode):

在睡眠模式下,只有 CPU 停止运行,内核时钟关闭,也就是程序暂停。

但外设和系统时钟继续工作。

这种模式适合于短时间内不需要 CPU 运算,但外设仍需保持活跃的场景。

IO 口状态保持和正常模式下一样。

可以通过任意一个中断或唤醒事件唤醒;唤醒后回到睡眠的位置向后执行。

停止模式(Stop Mode):

在停止模式中,关闭内核时钟、外设时钟,主时钟(HSE/HSI)被关闭,程序暂停,外设也停止工作。

只有低速时钟(LSI/LSE)继续运行。

保留内核1.8V供电,寄存器和 RAM 中的数据可以保持;

IO 口状态保持和正常模式下一样。

唤醒时间较短,适合需要较快响应的系统。

可以通过任意一个外部中断唤醒(EXTI);唤醒后可回到停止的代码处向后执行,但要重新初始化时钟和外设。

额外补充,ADC 和 DAC 不会自动停止工作,需要程序使其停止。 Flash 可以配置为 正常模式或者掉电模式。

待机模式(Standby Mode):

待机模式是最深的低功耗模式,关闭所有时钟,包括低速时钟,并且关闭了内部电压调节器 (内核1.8V供电) 。

寄存器和RAM数据不能保持(除了电源控制/状态寄存器(PWR_CSR)、备份寄存器,其他数据都丢失);

该模式适合长时间不需要响应的设备,唤醒后系统需完全重新初始化。

所有 IO 口均为高阻态,除了 RESET 引脚,以及使用了的 RTC 引脚和 启用了的 WAKEUP 引脚。

只有通过唤醒引脚(PA0)上升沿、RTC闹钟中断,或者复位唤醒;唤醒后相当于复位,从复位地址开始执行。

在上面的这些模式中:睡眠模式 适合于需要快速响应的场景,停止模式 和 待机模式 则适合于功耗要求较低且可以容忍较长唤醒时间的场景。

我们还需要知道,上面几个模式的 功耗由高到低 排序如下:

睡眠模式(Sleep Mode)> 停止模式(Stop Mode)> 待机模式(Standby Mode)

我们在实际使用 STM32 不同的系列内核芯片的时候,虽然大体上来说低功耗模式都差不多,但是我们还是有必要看一下对应的芯片手册中 Low-power modes 这一章节,排除有些芯片有些特除的模式。比如 本次测试使用的 STM32L010 手册如下(作为示例,没有把全部的模式截图上来):

在这里插入图片描述

本文我们的目的是怎么用,更深的一些相关理论与技术大家可以自行网上探究。

说明,本文以 STM32L010F4 芯片作为测试 。

二、 HAL 库休眠测试

我们本次使用 STM32CuBeMX 生成的代码对上面的三种模式进行实验测试,告诉大家怎么在生成的工程上面来使得 STM32 进入休眠模式。

我们知道使用 STM32CubeMX 可以一键生成代码,但是对于我们低功耗使用来说,我们还是要自己添加休眠程序的,HAL 库只是帮我们封装好了进入休眠的函数,我们什么时候进入休眠,如何唤醒还是需要自己写逻辑的!

2.1 HAL 低功耗相关函数

在 HAL 库中,有一个 stm32l0xx_hal_pwr.c 文件(这里是以 STM32L0 系列为例),里面包行了 HAL 写好的进入退出休眠函数,在 stm32l0xx_hal_pwr.h 头文件我们可以直接查看到这几个与低功耗有关的函数:

在这里插入图片描述

在上图中,我们已经做了基本的解释,实际上大家自己可以进入到函数原型,看一下官方的注释,基本上所有的问题都写的很清楚了 ,如下图:

(再一次说明官方资料的重要性,实际上只要告诉你东西在什么地方,然后剩下的直接可以阅读官方提供的东西,比很多网上文章更权威,也更加全面 )

在这里插入图片描述

2.2 使用测试

上面需要介绍的也介绍完毕了,接下来就开始来实际的测试一下这几种低功耗模式怎么操作。

2.2.1 Sleep Mode 测试

由上文我们可以知道, Sleep Mode 的进入函数为HAL_PWR_EnterSLEEPMode(),可以通过任意一个中断唤醒。

那我们做如下实验:

运行一段时间,让他进入 sleep mode ,然后通过外部中断(按钮)唤醒 。

为了演示效果,我们直接用 printf 通过串口助手看效果。

我们在 CubeMX 中做好几本设置,对于本次实验,我们可以直接使用芯片内部的时钟,虽然我们板子上外接了 32.768KHz 的低速时钟,但是这里用不用都不影响本次实验,所以在 CubeMX 中RCC 这一块什么都不选:

在这里插入图片描述

另外通过按钮唤醒,要根据原理图定义一下,下降沿触发中断,就是按键按下触发:

在这里插入图片描述

然后生成工程,编辑我们的工程如下:

在这里插入图片描述

上面我们可以看到,进入循环以后,打印一个消息就进入 sleep 模式,然后等待按钮按下,才会打印第二段消息。

但实际的情况是,我什么都没操作,他就循环的执行,这是为什么呢?

这是因为 Sleep Mode 是所有中断都可以唤醒,而我们系统运行 Systick 会一直运行,它每隔 1ms 中断一次,也会唤醒 MCU。 所以我们在进入 Sleep Mode 之前要关闭 Systick 定时器,睡眠过后再打开。

在 HAL 库中,关闭打开 Systick 定时器的函数为:

void HAL_SuspendTick(void);  //Suspends the Tick increment.
void HAL_ResumeTick(void);  // Resumes the Tick increment.

所以我们的程序应该改成如下:

while (1)
  {
    LED_ON;
    printf("get into sleep mode!\r\n");
    HAL_SuspendTick();
    HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON,PWR_SLEEPENTRY_WFI);
    HAL_ResumeTick();
    printf("wakeup by exit key button !!!\r\n");
    LED_OFF;
    HAL_Delay(1000);
    LED_ON;
    HAL_Delay(1000);
    LED_OFF;
    HAL_Delay(1000);
    //
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

现在如果不按按键,程序就会一直在 Sleep mode ,串口输出也会一直处于下面的状态直到按键按下为止:

在这里插入图片描述

这里还需要说明一下的是,程序上我们并没有去写按键中断的程序,因为不需要,我们只要设定了按键下降沿触发中断就可以,即便触发了中断什么都不做,系统也会唤醒。

意思就是,对于 HAL 库工程而言,只要 stm32l0xx_it.c 中里面的中断只要触发了,就会把 MCU 从 Sleep mode 唤醒,不用管触发中断后有没有任何的操作。

2.2.2 Stop Mode 按键唤醒

接下来我们来看看 Stop Mode,该模式进入函数为HAL_PWR_EnterSTOPMode(),可以通过任意一个外部中断唤醒。

那我们做如下实验:

运行一段时间,让他进入 stop mode ,然后通过外部中断(按钮)唤醒 。

这里 Systick 我们就不需要单独关闭了,因为它唤醒不了,再者外设时钟停止了,其实 Systick 定时器也停止了。

第一次写和 sleep mode 一样,还是粗心大意,忘了唤醒后需要重新初始化时钟和外设。

在这里插入图片描述

最后加上时钟初始化就正常了,代码如下:

while (1)
  {
    LED_ON;
    printf("get into stop mode!\r\n");
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_SLEEPENTRY_WFI);
    SystemClock_Config();
    printf("wakeup by exit key button !!!\r\n");
    LED_OFF;
    HAL_Delay(1000);
    LED_ON;
    HAL_Delay(1000);
    LED_OFF;
    HAL_Delay(1000);
    //
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

那这里有个疑问,命名是需要重新初始化时钟和外设,为什么我这里只重新初始化时钟就好了。

我们知道在 STOP 模式下,IO 状态会保持和正常模式下一致,比如在我的 STOP 模式下面,LED 灯会保持点亮也说明了这一点 。 在我示例中的串口和 IO 口(LED)没有关闭,配置也没有改变,所以唤醒以后不需要重新初始化他们。

但是这只是测试,实际使用低功耗设备不可能保持 LED 灯常亮。

2.2.3 Stop Mode RTC唤醒

测试完按键唤醒,我们还需要测试一个比较常用的方法, RTC 唤醒。

那么这时候我们得重新在 STM32CubeMX 里面设置一下,先设置一下 RCC :

在这里插入图片描述

然后在设置下 RTC ,具体操作如下图:

在这里插入图片描述

上面的 Wake Up Counter 设置说明有错误,如果想要为 5s ,应该把 Wake Up Counter 设置为 4。

还得记得把中断打开,可以看到 RTC 中断也是挂载 EXTI 外部中断线上的:

在这里插入图片描述

最后别忘了在时钟配置界面,把 RTC 选择为外部晶振 ,如下图:

在这里插入图片描述

设置完成以后,我们在写一下程序,我们可以看到工程里面会多了rtc.c 文件,这里包含了 RTC 的初始化 ,我们首先在main.c 里面写上如下代码:

	...
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */
  // HAL_TIM_Base_Start_IT(&htim2); 
  
  printf("STM32L010F4 lowpower test!!!\r\n");
  printf("reset delay 3s for down load!!!\r\n");
  HAL_Delay(3000);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    LED_ON;
    printf("get into stop mode!\r\n");
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_SLEEPENTRY_WFI);
    printf("wakeup by RTC !!!\r\n");
    LED_OFF;
    HAL_Delay(500);
    //
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

然后在 rtc.c 里面实现以下 RTC 的中断回调函数,其实这个回调函数放在main.c 中也一样,当然记得,操作之前先打开时钟:

/* USER CODE BEGIN 1 */
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
  RTC_TimeTypeDef sTime;
  RTC_DateTypeDef sData;
  SystemClock_Config();
  if(HAL_RTC_GetTime(hrtc,&sTime,RTC_FORMAT_BIN) == HAL_OK){
    HAL_RTC_GetDate(hrtc,&sData,RTC_FORMAT_BIN);
    printf("RTC current time: %02d:%02d:%02d\r\n",sTime.Hours,sTime.Minutes,sTime.Seconds);
  }

}
/* USER CODE END 1 */

然后实际测试结果如下:

在这里插入图片描述

发现了一个错误,在设置 Wake Up Counter 值的时候,我们设置的是 5, 这里中断一次为 6s ,如果要是5s ,Wake Up Counter 应该为4。

修改 RTC 唤醒周期

然后还要说明一下,如果想修改唤醒周期,在不修改频率的情况下,修改 Wake Up Counter 的值也可以实现,比如改成 10s 一次中断,那么使用如下函数:


HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 9, RTC_WAKEUPCLOCK_CK_SPRE_16BITS)

第一个参数为 RTC 对象指针,第二个参数就是 Wake Up Counter ,第三个参数为 Wake Up Clock

比如在执行完一次以后,就把时间修改为 10s:

在这里插入图片描述

当然,也可以放在唤醒之后在主函数中,根据其他条件按需求修改,这里只是一个示例。

除了上面这种办法,我在网上也参考了网上的一个修改时间的代码,可以直接设定为在多少秒以后实现下一次唤醒,代码如下:

/*
读取当前 RTC 值,再加上需要延时的 秒数,再指定下一次 RTC 报警的 RTC 时钟
因为有一个函数 STM32L010 没有,本人没有测试,大家复制使用起来需要自行测试。
*/
void set_next_time_Alarm_IT(unsigned int Seconds)
{
  RTC_TimeTypeDef rTime;
  RTC_AlarmTypeDef ATime;
  unsigned char Minutes,Hours;
  if(HAL_RTC_GetTime(&hrtc,&rTime,RTC_FORMAT_BIN) != HAL_OK) Error_Handler();
  Hours = (u8)(Seconds/3600);
  Minutes = (u8)((Seconds % 3600) / 60);
  Seconds = (u8)((Seconds % 3600) % 60);

  rTime.Seconds += (u8)Seconds;
  if(rTime.Seconds >= 60){
    rTime.Seconds -= 60;
    Minutes += 1;
  }
  rTime.Minutes += Minutes;
  if(rTime.Minutes >= 60){
    rTime.Minutes -= 60;
    Hours += 1;
  }
  rTime.Hours += Hours;

  ATime.AlarmTime = rTime;
  ATime.Alarm = RTC_ALARM_A;  

  // HAL_RTCEx_SetSecond_IT(&hrtc);// STM32L010没有

  HAL_RTC_SetAlarm_IT(&hrtc,&ATime,RTC_FORMAT_BIN);

}

以上就是 Stop Mode 的测试示例,主要需要注意的就是,从 Stop Mode 唤醒,要记得重新初始化时钟和外设(有必要的话)。

2.2.4 Standby Mode 测试

最后到了最低功耗的 Standby Mode 模式,Standby Mode 模式有点类似于关机,休眠后唤醒会从头开始制执行。

我们可以直接在上面一个工程上直接修改,整体效果如下:

在这里插入图片描述

上面的示例中有几点需要说明一下:

  • 上面代码中判断了一个标志位PWR_FLAG_SB ,这个表示为 Standby Flag ,这个标志位专门用于指示微控制器是否从待机模式(STANDBY Mode)唤醒。如果微控制器是从待机模式唤醒的,这个标志位会被设置为SET。
    所以可以通过这个位判断是从什么模式唤醒。

  • 在进入Standby 模式之前,我使用了HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1|PWR_WAKEUP_PIN3); 禁用 Wakeup 引脚。因为我们使用 RTC 唤醒,禁用这两个引脚可以使得它们变成高阻态,相对来说,更能节约那么一点电。
    至于为什么这里是 1 和 3 ,没有2 ,这个是不同的芯片决定的,虽然在手册中官方是这么说的:
    在这里插入图片描述
    但实际上他根本没有 PWR_WAKEUP_PIN2 ,因为写上去会报错= =!然后通过 CubeMX 的图形话界面也可以验证这一点。

  • 这里我们可以看到串口根本没有打印出 RTC 时间,这是因为通过 RTC 中断唤醒以后, MCU直接就从头开始运行了,它不会运行到中断处理函数中去。

如果我们想要看到 RTC 时间,我们需要再次修改一下,我们直接改成如下 :

在这里插入图片描述

看一下结果,好像有点问题:

在这里插入图片描述

我们命名是定义的每 5 S 唤醒一次,这里怎么变成 3S 了,这里稍微测试了一下,是因为我忽略了一个标志位:PWR_FLAG_WU ,在进入低功耗模式钱,需要清除一下这个标志位,这个标志位表示微控制器是由于外部唤醒信号(如外部中断或RTC闹钟)而从低功耗模式(如待机模式STANDBY或停止模式STOP)唤醒的。

最后代码修改成如下:

printf("STM32L010F4 lowpower test!!!\r\n");

  if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB) == SET){
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
    if(HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN) == HAL_OK){
      printf("RTC current time: %02d:%02d:%02d\r\n",sTime.Hours,sTime.Minutes,sTime.Seconds);
    }
    printf("standby reset\r\n");
  }
  else{
    printf("normal reset!!!\r\n");
  }
  printf("reset delay 3s for down load!!!\r\n");
  LED_ON;
  HAL_Delay(1000);
  LED_OFF;
  HAL_Delay(1000);
  LED_ON;
  HAL_Delay(1000);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    printf("get into standby mode!\r\n");
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1|PWR_WAKEUP_PIN3);
    HAL_PWR_EnterSTANDBYMode();
    //printf("wakeup by RTC !!!\r\n");  不会走到这一步
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

最后看下结果,才是正常的:

在这里插入图片描述

细节问题之如何节约内存空间

这里我还有个细节问题,在上面的测试中,我都使用了 printf ,但是 STM32L010 的 Flash 非常小,只有 16K,使用 printf 函数非常占用 flash 空间,虽然测试无所谓,但是在这种简单测试上,我再加上点传感器驱动,就放不下了。

这里呢我们可以使用 函数HAL_UART_Transmit 来实现 printf 同样的效果,所以我把上面的程序改成下面这种方式:

  /* USER CODE BEGIN 2 */
  // HAL_TIM_Base_Start_IT(&htim2); 
  // printf("STM32L010F4 lowpower test!!!\r\n");
  HAL_UART_Transmit(&hlpuart1, (uint8_t *)"STM32L010F4 lowpower test!!!\r\n", strlen("STM32L010F4 lowpower test!!!\r\n"), 100);

  if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB) == SET){
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
    if(HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN) == HAL_OK){
      // printf("RTC current time: %02d:%02d:%02d\r\n",sTime.Hours,sTime.Minutes,sTime.Seconds);
      size_t len = snprintf((char *)buffer, sizeof(buffer), "RTC current time: %02d:%02d:%02d\r\n", sTime.Hours,sTime.Minutes,sTime.Seconds);
      HAL_UART_Transmit(&hlpuart1, buffer, len, 100);
    }
    // printf("standby reset\r\n");
    HAL_UART_Transmit(&hlpuart1, (uint8_t *)"standby reset\r\n", strlen("standby reset\r\n"), 100);
  }
  else{
    // printf("normal reset!!!\r\n");
    HAL_UART_Transmit(&hlpuart1, (uint8_t *)"normal reset!!!\r\n", strlen("normal reset!!!\r\n"), 100);
  }
  // printf("reset delay 3s for down load!!!\r\n");
  HAL_UART_Transmit(&hlpuart1, (uint8_t *)"reset delay 3s for down load!!!\r\n", strlen("reset delay 3s for down load!!!\r\n"), 100);
  LED_ON;
  HAL_Delay(1000);
  LED_OFF;
  HAL_Delay(1000);
  LED_ON;
  HAL_Delay(1000);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    // printf("get into standby mode!\r\n");
    HAL_UART_Transmit(&hlpuart1, (uint8_t *)"get into standby mode!\r\n", strlen("get into standby mode!\r\n"), 100);
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1|PWR_WAKEUP_PIN3);
    HAL_PWR_EnterSTANDBYMode();
    //printf("wakeup by RTC !!!\r\n");  不会走到这一步
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

编译过后看一下 text 段,这么一点点代码就已经节约了差不多 2K 的内存空间 = =!:

在这里插入图片描述

好了,到这里 Standby Mode 的测试也完成了。

三、 关于低功耗的其他细节说明

最后呢,我们还有一些其他的细节问题,来补充说明一下。

3.1 PWR_FLAG_WUPWR_FLAG_SB

在上面我们没有特意的对这两个标志位做说明,然而在测试过程中也确实因为标志位出现了问题,所以在这里补充说明一下:

  • PWR_FLAG_WU(Wakeup Flag)

这个标志位表示微控制器是由于外部唤醒信号(如外部中断或 RTC 闹钟)而从低功耗模式(如待机模式STANDBY或停止模式STOP)唤醒的。在微控制器从低功耗模式唤醒后,这个标志位会被设置为SET。

在程序中,通常需要清除这个标志位,以避免微控制器被立即重新唤醒。使用 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

  • PWR_FLAG_SB(Standby Flag)

这个标志位专门用于指示微控制器是否从待机模式(STANDBY Mode)唤醒。如果微控制器是从待机模式唤醒的,这个标志位会被设置为 SET。

这个标志位可以用来区分微控制器是正常上电复位还是从待机模式唤醒的复位。

在程序中,也需要清除这个标志位,以准备下一次可能的待机模式进入。

总结来说,PWR_FLAG_WU 是一个通用的唤醒标志,用于指示任何低功耗模式下的唤醒事件,而PWR_FLAG_SB是专门用于指示从待机模式唤醒的情况。

在实际使用中,进入 stop 或者 standby 模式之前,都得记得清除一下 PWR_FLAG_WU 标志位!!!

3.2 低功耗模式下的烧录问题

在进入休眠状态后,STM32 是无法进行烧录的。

所以在上面测试的时候可以看到,我都会在复位后预留一点时间给与烧录。当然实际使用中唤醒工作基本也就是瞬间的事情,是无法采用这种方式的。这时候需要一直按住复位按键,在下载进行的时候松开,也是一种办法。

如果我们使用 JLink 的话,不管 STM32 是否休眠,可以直接全部擦除了以后,再进行烧录。

当然,还有其他的一些方式, ISP 下载啊, 使用 STLINK 下载等等。

3.3 休眠模式下的 IO 口问题

在休眠模式下 ,IO 口的配置也会影响着功耗。

我们知道在 Standby Mode 模式下面, STM32 会将除了 复位引脚,被使能的唤醒引脚,和 RTC 引脚意外,都设置为高阻态,这有利于把功耗保持在最低的状态。

除了这个模式,在其他低功耗模式中,我们其实也有必要注意一下 不用的 IO 口,我们可以手动的将其他 IO 口设置为高阻态,一般模拟输入(虽然是说 不用的 IO 默认就是这种状态)。在 CuBeMX 中,我们有一个选项可以勾选上,可以自动完成这种配置:

在这里插入图片描述

在休眠过程中,有些需要用到的 IO 口也可以进行一定的配置来节约功耗,有几点要注意一下:

  • 如果外部晶振不用的话,连接晶振的 IO 口不能配置为浮空输入,除非你的外部有下拉电阻。需要配置为输入上拉或者下拉,或者输出低电平。
  • 输入引脚,如果高阻状态端口是高电平,就设成上拉输入,如果高阻状态是低电平,设成下拉输入,如果高阻是中间状态,设成模拟输入;
  • 输出引脚会耗电,如果在休眠之后不需要用到,可以设置为输入,唤醒后再初始化;
  • 中断输入的引脚如果有上下拉,则会消耗电流,这时候可以在合适的情况下增大上下拉电阻,相对能够节能;

3.4 关于 MCU 的时钟

我们的 系统时钟都是可以设置的,一般对于普通应用,或许大家都习惯性的给到他最大的时钟周期,比如 72M ,32M 之类的。

但是时钟越大,功耗越大,当然,他响应速度也是最快的。 时钟越慢,功耗越低,但是运行速度也更低。

所以在实际应用中,需要根据自己的实际情况,根据需求选择合适的时钟周期,也能在一定程度上节约功耗。

这里举个例子,对于一些传感器采集的模型,完全可以使用低速率的时钟周期,因为在很多时候,采集传感器也会需要一定时间的等待,这等待的过程运行速度就不重要了,反而速度越快,额外消耗的功耗就越多。

结语

本文不仅对 STM32 的低功耗模式进行了一个介绍,然后还在 STM32CubeMX 环境下面对每个模式进行了详细的使用说明。

看完本文,相信大家应该都知道如何使用 HAL 库进行 STM32 的低功耗开发了。当然真正的低功耗,除了 MCU 本身,外围电路的设计也是很重要的,所以大家在进行低功耗测试的时候,如果测量的结果不够满意,多注意一下文中提到的其他细节说明,而且还得结合外围电路一起分析。

好了,本文就到这里!谢谢大家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/916125.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NVR小程序接入平台/设备EasyNVR多个NVR同时管理设备接入:海康NVR 3.0提示不在线如何处理?

在视频监控领域,设备的兼容性和互操作性一直是用户关注的重点。海康NVR管理平台EasyNVR作为一款轻量级的视频监控平台,凭借其强大的兼容性、可扩展性和丰富的功能,成为了公共安全领域“云平台”解决方案的杰出代表。然而,在实际应…

【C语言】Union

一.Union的用法 1.什么是Union? union 共用体名{ 成员列表 }; union,“联合体、共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。 2.为什么使用union&#xff1…

2023_Spark_实验十五:SparkSQL进阶操作

实验目标 通过实践掌握Spark SQL中复杂查询(包括子查询、窗口函数、联接等)的实现方式。了解如何通过合理的数据分区和缓存策略进行性能优化。实现一个基于Spark SQL的ETL数据处理流程,应用相关优化技巧。 实验背景 在本实验中&#xff0c…

PaoluGPT——窥视未知

上一题已经得到一个flag,还有一个flag 根据题目信息,说明还有一些聊天记录是没有公开的,另一个flag就在这些未公开的聊天记录中 下载题目附件看看,发现里面有个main.py: 可以看到有两条SQL查询语句,猜测应该…

初识C++ (三)

如果很迷茫的话,就学习吧 引用 一. 引用的概念 “引用(Reference)是 C 相对于C语言的又一个扩充。引用可以看做是数据的一个别名,通过这个别名和原来的名字都能够找到这份数据。 具体是什么意思呢? 我们这里来举个例子 比如:李逵&#xff0…

南京观海微电子----驱动电路中误导通及应对方法

驱动电路中的误导通 功率器件如 MOSFET、IGBT 可以看作是一个受门极电压控制的开关。当门极电压大于开通阈值时,功率器件就会 被开通,而当门极电压低于开通阈值时就会被关断。但是在实际的应用中,由于器件及外围线路寄生参数的影响&#xff0…

C++ —— 哈希详解 - 开散列与闭散列

目录 1. 哈希的概念 1.1 直接定址法 1.2 哈希冲突 1.3 负载因子 1.4 哈希函数 1.4.1 除法散列法/除留余数法 1.4.2 乘法散列法 1.4.3 全域散列法 1.5 处理哈希冲突 1.5.1 开放定址法(闭散列) 1. 线性探测(挨着查找) 2.…

NVR批量管理软件EasyNVR大华NVR管理平台如何在Linux环境下部署?

随着视频监控技术的不断进步,NVR(网络视频录像机)批量管理软件在维护公共安全、提升管理效能方面发挥着越来越重要的作用。EasyNVR作为一款功能强大的NVR批量管理软件,凭借其高效的视频处理能力、灵活的设备接入能力和智能分析功能…

js技能提升——手搓图片组展示——基础积累

// 图片组展示[{name:,src:}]showAltPics(picList[], index0) {if (picList.length 0) {layer.msg("图片路径不对,请重试!", { time: 2000 });return false;}//解析展示let inPicListHtml ;let indexPic picList[index];for (let i 0; i &…

<项目代码>YOLOv8 番茄识别<目标检测>

YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为一个回归问题,能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法(如Faster R-CNN),YOLOv8具有更高的…

Llama架构及代码详解

Llama的框架图如图: 源码中含有大量分布式训练相关的代码,读起来比较晦涩难懂,所以我们对llama自顶向下进行了解析及复现,我们对其划分成三层,分别是顶层、中层、和底层,如下: Llama的整体组成…

冒泡选择法(c基础)

适合对象c语言初学者。 冒泡选择法 作用对一个数组进行排序。(介绍一下数组(c基础)(详细版)-CSDN博客) 核心要点 1: 数组元素个数 sz 2: 比较后的交换。 核心思路 进行(sz - 1)趟,每一趟把最大数的放到末尾。其…

深入浅出《钉钉AI》产品体验报告

1. 引言 随着人工智能技术的迅猛发展,企业协同办公领域迎来了新的变革。钉钉作为阿里巴巴集团旗下的企业级通讯与协同办公平台,推出了钉钉AI助理,旨在提高工作效率,优化用户体验。本报告将对钉钉AI助理进行全面的产品体验分析&am…

【GPTs】Gif-PT:DALL·E制作创意动图与精灵动画

博客主页: [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 💯GPTs指令💯前言💯Gif-PT主要功能适用场景优点缺点 💯小结 💯GPTs指令 中文翻译: 使用Dalle生成用户请求的精灵图动画&#…

一文看懂什么1688跨境(专业解析)

1688跨境是什么? 最近火出圈的一个新词 今天老余带大家走近1688跨境 首先为什么会出现1688跨境? 因为: 新型服务商崛起,反向海淘成趋势 在过去三年,1688涌现了一批新型的服务商: 他们帮助海外B类买家到1688采购&#xff…

SpringBoot+Vue3实现数据可视化大屏

前端工程的地址:UserManagerFront: 数据可视化前端 (gitee.com) 效果展示,可以展现出来了,样式可能还有一些丑。 后端代码 后端主要是拿到数据并对数据进行处理,按照前端需要的格式进行返回即可。 import com.njitzx.entity.Student; impor…

<项目代码>YOLOv8 手机识别<目标检测>

YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为一个回归问题,能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法(如Faster R-CNN),YOLOv8具有更高的…

算法定制LiteAIServer摄像机实时接入分析平台烟火识别检测算法

在公共安全领域,火灾的及时发现与处理是保障人民群众生命财产安全的重要手段。传统的烟火检测手段受限于人工巡查的局限,难以做到全天候、无遗漏的监控。然而,随着人工智能技术的飞速发展,LiteAIServer摄像机实时接入分析平台烟火…

JMeter与大模型融合应用之JMeter日志分析服务化实战应用

JMeter与大模型融合应用之JMeter日志分析服务化 引言 在当今的互联网时代,网站和应用程序的性能直接影响到用户的体验和业务的成功。为了保证系统的稳定性和高效性,性能测试成为了软件开发过程中的一个重要环节。在这其中,Apache JMeter作为一款开源的性能测试工具,凭借其…

【Pikachu】任意文件上传实战

将过去和羁绊全部丢弃,不要吝惜那为了梦想流下的泪水。 1.不安全的文件上传漏洞概述 不安全的文件上传漏洞概述 文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像、上传附件等等。当用户点击上传按钮后,后台会对上传的…