【BLE】STM32WB55_低功耗(十一)

文章目录

      • [1. 外设时钟](#1. 外设时钟)
      • [2. 系统电压配置](#2. 系统电压配置)
      • [3. SMP配置](#3. SMP配置)
      • [4. 进低功耗流程](#4. 进低功耗流程)

1. 外设时钟

c 复制代码
/**
  * @brief Peripherals Common Clock Configuration
  * @retval None
  */
void PeriphCommonClock_Config(void)
{
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Initializes the peripherals clock
  */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS|RCC_PERIPHCLK_RFWAKEUP;
  PeriphClkInitStruct.RFWakeUpClockSelection = RCC_RFWKPCLKSOURCE_LSE;
  PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSE;
  PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE0;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN Smps */

  // 指定本次要配置的两类外设时钟:SMPS(内置开关电源控制器)时钟 + RFWAKEUP(射频唤醒模块)时钟
  // 配置射频唤醒模块的时钟源:选择LSE(低速外部晶振,默认32.768kHz,低功耗下仍可稳定运行,适配BLE低功耗唤醒需求)
  // 配置SMPS开关电源的时钟源:选择HSE(高速外部晶振,默认32MHz,精度高稳定性好,保障供电控制的准确性)
  // 配置SMPS时钟分频系数:选择RANGE0(对应分频比为1,即SMPS时钟直接等于HSE输入频率,无分频)
  
  /* USER CODE END Smps */
}

2. 系统电压配置

c 复制代码
static void SystemPower_Config(void)
{
  /**
   * Select HSI as system clock source after Wake Up from Stop mode
   * 功能:配置MCU从Stop低功耗模式唤醒后的系统时钟源
   * 设置Stop模式唤醒后使用HSI(高速内部时钟)作为系统时钟,不需要等待外部晶振起振,可大幅降低唤醒耗时,适合低功耗快速响应场景
   */
  LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI);

  /* Initialize low power manager */
  UTIL_LPM_Init();
  /* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */
  /*  在启动CPU2(Cortex-M0+ 射频核心)前,先配置CPU2的初始电源模式为SHUTDOWN关机模式,未启动时保持最低功耗,避免额外耗电 */
  LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
// 编译宏判断:仅当工程配置中启用了USB外设功能时,才编译执行以下USB电源配置代码
#if (CFG_USB_INTERFACE_ENABLE != 0)
  /**
   *  Enable USB power
   */
  HAL_PWREx_EnableVddUSB();
#endif /* CFG_USB_INTERFACE_ENABLE != 0 */

  return;
}

3. SMP配置

c 复制代码
void Init_Smps(void)
{
#if (CFG_USE_SMPS != 0)
  /**
   *  Configure and enable SMPS
   *
   *  The SMPS configuration is not yet supported by CubeMx
   *  when SMPS output voltage is set to 1.4V, the RF output power is limited to 3.7dBm
   *  the SMPS output voltage shall be increased for higher RF output power
   * 配置SMPS启动阶段的最大限流值为80mA。SMPS启动瞬间需要较大电流给后端储能电容充电,
		80mA是兼顾启动速度和过流保护的常用配置,可覆盖BLE射频发射峰值电流(20~50mA)的需求,避免启动过流损坏电源模块。
	 * 设置SMPS稳定工作时的输出电压为1.4V。该电压是给MCU内核、内存、外设逻辑、BLE射频模块供电的核心电压,1.4V是STM32WB主频运行在64MHz、BLE正常收发的标准配置,相比更高电压(如1.5V)可降低10%左右的运行功耗。
	 * 使能SMPS电源模块,配置生效后SMPS将替代默认的内部LDO为核心域供电,大幅降低运行和休眠状态下的功耗。
   */


  LL_PWR_SMPS_SetStartupCurrent(LL_PWR_SMPS_STARTUP_CURRENT_80MA);
  LL_PWR_SMPS_SetOutputVoltageLevel(LL_PWR_SMPS_OUTPUT_VOLTAGE_1V40);
  LL_PWR_SMPS_Enable();
#endif /* CFG_USE_SMPS != 0 */

  return;
}

4. 进低功耗流程

c 复制代码
  while (1)
  {
    /* USER CODE END WHILE */
    MX_APPE_Process();

    /* USER CODE BEGIN 3 */
    
  }
c 复制代码
void MX_APPE_Process(void)
{
  /* USER CODE BEGIN MX_APPE_Process_1 */

  /* USER CODE END MX_APPE_Process_1 */
  UTIL_SEQ_Run(UTIL_SEQ_DEFAULT);
  /* USER CODE BEGIN MX_APPE_Process_2 */

  /* USER CODE END MX_APPE_Process_2 */
}
c 复制代码
  UTIL_SEQ_ENTER_CRITICAL_SECTION_IDLE( );
  local_taskset = TaskSet;
  local_evtset = EvtSet;
  local_taskmask = TaskMask;
  if ((local_taskset & local_taskmask & SuperMask) == 0U)
  {
    if ((local_evtset & EvtWaited)== 0U)
    {
      UTIL_SEQ_Idle( );
    }
  }
  UTIL_SEQ_EXIT_CRITICAL_SECTION_IDLE( );
c 复制代码
void UTIL_SEQ_Idle(void)
{
#if (CFG_LPM_SUPPORTED == 1)
  UTIL_LPM_EnterLowPower();
#endif /* CFG_LPM_SUPPORTED == 1 */
  return;
}

关于官方定义的这个低功耗管理逻辑

官方的逻辑是反向思维

如果不是什么就什么

而不是

如果是什么就什么

c 复制代码
void UTIL_LPM_EnterLowPower( void )
{
  //进入临界区
  UTIL_LPM_ENTER_CRITICAL_SECTION_ELP( );
  //如果停止模式不使能标志 不是  不置位 = 
  if( StopModeDisable != UTIL_LPM_NO_BIT_SET )
  {
    /**
     * At least one user disallows Stop Mode
     * SLEEP mode is required
     */
      UTIL_PowerDriver.EnterSleepMode( );
      UTIL_PowerDriver.ExitSleepMode( );
  }
  else
  { 
    if( OffModeDisable != UTIL_LPM_NO_BIT_SET )
    {
      /**
       * At least one user disallows Off Mode
       * STOP mode is required
       */
        UTIL_PowerDriver.EnterStopMode( );
        UTIL_PowerDriver.ExitStopMode( );
    }
    else
    {
      /**
       * OFF mode is required
       */
      UTIL_PowerDriver.EnterOffMode( );
      UTIL_PowerDriver.ExitOffMode( );
    }
  }
  
  UTIL_LPM_EXIT_CRITICAL_SECTION_ELP( );
}

这两个标志是低功耗模式控制标志位。初始为0

//停止模式不使能标志-不置位

StopModeDisable = UTIL_LPM_NO_BIT_SET; //0

//关机模式不使能标志-不置位

OffModeDisable = UTIL_LPM_NO_BIT_SET; //0

初始化为0

c 复制代码
void UTIL_LPM_Init( void )
{
	//停止模式不使能标志-不置位
  StopModeDisable = UTIL_LPM_NO_BIT_SET; //0
  //关机模式不使能标志-不置位
  OffModeDisable = UTIL_LPM_NO_BIT_SET;  //0
  UTIL_LPM_INIT_CRITICAL_SECTION( );
}
c 复制代码
typedef enum
{
  CFG_LPM_APP, // APP 0
  CFG_LPM_APP_BLE, // BLE 1
  /* USER CODE BEGIN CFG_LPM_Id_t */

  /* USER CODE END CFG_LPM_Id_t */
} CFG_LPM_Id_t;
typedef enum
{
  UTIL_LPM_ENABLE=0,
  UTIL_LPM_DISABLE,
} UTIL_LPM_State_t;

跟着初始化一步步走

c 复制代码
void MX_APPE_Init(void)
{
/* USER CODE END APPE_Init_1 */
  appe_Tl_Init();	/* Initialize all transport layers */
}
下一级
static void appe_Tl_Init(void)
{
  shci_init(APPE_SysUserEvtRx, (void*) &SHci_Tl_Init_Conf);
  return;
}
下一级
static void APPE_SysUserEvtRx(void * pPayload)
{
    APP_DBG_MSG(">>== SHCI_SUB_EVT_CODE_READY\n\r");
    APPE_SysEvtReadyProcessing(pPayload);
}
下一级
static void APPE_SysEvtReadyProcessing(void * pPayload)
{
    APP_BLE_Init();
    UTIL_LPM_SetOffMode(1U << CFG_LPM_APP, UTIL_LPM_ENABLE);
}
APP_BLE_Init里面
void APP_BLE_Init(void)
{
  /**
   * Do not allow standby in the application
   */
  UTIL_LPM_SetOffMode(1 << CFG_LPM_APP_BLE, UTIL_LPM_DISABLE);
}
c 复制代码
先执行
 /**
  * Do not allow standby in the application
  */
 UTIL_LPM_SetOffMode(1 << CFG_LPM_APP_BLE, UTIL_LPM_DISABLE);
* 1<<1 = 2
* OffModeDisable  |= 2;
* OffModeDisable   = 2;

后执行
UTIL_LPM_SetOffMode(1U << CFG_LPM_APP, UTIL_LPM_ENABLE);
* 1<<0 = 1
* OffModeDisable &= ~1;
* OffModeDisable &= 0;
* OffModeDisable  = 2 & 0 = 2;
* OffModeDisable  = 2; 
这两个执行完毕 结果OffModeDisable  = 2;
c 复制代码
置位逻辑
void UTIL_LPM_SetOffMode( UTIL_LPM_bm_t lpm_id_bm, UTIL_LPM_State_t state )
{
  UTIL_LPM_ENTER_CRITICAL_SECTION( );
  
  switch(state)
  {
  case UTIL_LPM_DISABLE:
    {
      OffModeDisable |= lpm_id_bm;
      break;
    }
  case UTIL_LPM_ENABLE:
    {
      OffModeDisable &= ( ~lpm_id_bm );
      break;
    }
  default :
    {
      break;
    }
  }
  
  UTIL_LPM_EXIT_CRITICAL_SECTION( );
}

两个全局标志都是位掩码,每1bit对应一个业务/外设模块的低功耗禁用申请:

StopModeDisable:值为UTIL_LPM_NO_BIT_SET(也就是0)=

所有模块都允许进入Stop及更低功耗模式;非0=至少有1个模块禁止进入Stop模式

OffModeDisable:值为0=所有模块都允许进入Off最低功耗模式;非0=至少有1个模块禁止进入Off模式

c 复制代码
此时
StopModeDisable  = 0;
OffModeDisable  = 2;
void UTIL_LPM_EnterLowPower( void )
{
  // 进临界区:关中断,防止低功耗切换过程被中断打断出现逻辑异常
  UTIL_LPM_ENTER_CRITICAL_SECTION_ELP( );
 //【只要有任何一个模块申请了"不让进Stop模式"】 → 那就只能进最浅的Sleep模式
 //如果StopModeDisable是0 → :【所有模块都同意可以进Stop模式】
  if( StopModeDisable != UTIL_LPM_NO_BIT_SET )
  {
    /**
     * At least one user disallows Stop Mode
     * SLEEP mode is required
     */
      UTIL_PowerDriver.EnterSleepMode( );
      UTIL_PowerDriver.ExitSleepMode( );
  }
  else
  { 
   //【只要有任何一个模块申请了"不让进Off模式"】 → 那就进中等深度的Stop模式
   //如果OffModeDisable也是0 → :【所有模块都同意可以进Off模式】
    if( OffModeDisable != UTIL_LPM_NO_BIT_SET )
    {
      /**
       * At least one user disallows Off Mode
       * STOP mode is required
       */
        UTIL_PowerDriver.EnterStopMode( );
        UTIL_PowerDriver.ExitStopMode( );
    }
    else
    {
      /**
       * OFF mode is required
       */
      UTIL_PowerDriver.EnterOffMode( );
      UTIL_PowerDriver.ExitOffMode( );
    }
  }
  
  UTIL_LPM_EXIT_CRITICAL_SECTION_ELP( );
}
相关推荐
染予2 小时前
Ka 阵面星历下发与执行逻辑说明
stm32·嵌入式硬件
新晨单片机设计7 小时前
S010A-基于STM32单片机水温控制系统(数码管显示)【Proteus仿真+Keil程序+原理图】
stm32·单片机·嵌入式硬件
Brilliantwxx8 小时前
【STM32】 初认识USART串口
linux·stm32·单片机·嵌入式硬件·架构
沐欣工作室_lvyiyi9 小时前
基于STM32的人脸识别门禁系统的设计与实现(论文+源码)
stm32·单片机·嵌入式硬件
zcmodeltech13 小时前
智慧矿山沙盘模型多场景控制系统设计——基于STM32与Modbus RTU的智能开采、无人矿卡、数字孪生全场景联动方案
数据库·stm32·单片机·嵌入式硬件·物联网
qq_4029957513 小时前
Secure Boot Part 3 —— 信任根和信任链
arm开发·stm32·信任链
youcans_13 小时前
【嵌入式软件AI编程】03. STM32 VS Code 开发环境与工具链
stm32·单片机·ai编程·嵌入式软件·claude code
星河单片机14 小时前
STM32读取电阻式土壤湿度模块+OLED显示完整教程
stm32·单片机·嵌入式硬件·土壤湿度
影寂ldy15 小时前
C# UdpClient 单播 三种通信版本
stm32·单片机·c#