【BLE】STM32WB55_低功耗(十一)

1. 外设时钟


/**
  * @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. 系统电压配置

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配置

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. 进低功耗流程

  while (1)
  {
    /* USER CODE END WHILE */
    MX_APPE_Process();

    /* USER CODE BEGIN 3 */
    
  }
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 */
}
  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( );
void UTIL_SEQ_Idle(void)
{
#if (CFG_LPM_SUPPORTED == 1)
  UTIL_LPM_EnterLowPower();
#endif /* CFG_LPM_SUPPORTED == 1 */
  return;
}

关于官方定义的这个低功耗管理逻辑
官方的逻辑是反向思维
如果不是什么就什么
而不是
如果是什么就什么


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

void UTIL_LPM_Init( void )
{
	//停止模式不使能标志-不置位
  StopModeDisable = UTIL_LPM_NO_BIT_SET; //0
  //关机模式不使能标志-不置位
  OffModeDisable = UTIL_LPM_NO_BIT_SET;  //0
  UTIL_LPM_INIT_CRITICAL_SECTION( );
}
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;

跟着初始化一步步走


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);
}
先执行
 /**
  * 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;
置位逻辑
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模式

此时
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( );
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值