跳转到主要内容

STM32MX电源管理低功耗模式

cathy 提交于

<strong><font color="#004a85">前言:</font> </strong>

ST官方例程:(直接移植直接用,接口是现成的)

在你STM32Cube固件库安装路径下.

.\..\STM32Cube\Repository\STM32Cube_FW_F4_V1.23.0\Projects\STM32F429I-Discovery\Examples\PWR\PWR_CurrentConsumption

例程和测试程序下载链接:<a href="https://download.csdn.net/download/sudaroot/10891176&quot; title="STM32MX电源管理低功耗模式官方例程和测试程序-C/C++其他资源-CSDN下载">STM32MX电源管理低功耗模式官方例程和测试程序-C/C++其他资源-CSDN下载</a>

下面手册文字截图来源于《STM32F4xx中文参考手册.PDF》的第5 电源控制器(PWR)的5.3 低功耗模式

<strong><font color="#004a85">STM32电源三种低功耗模式介绍</font> </strong>

<center><img src="http://mcu.eetrend.com/files/2021-11/博客/100555157-226404-1.png&quot; alt=“STM32MX电源管理低功耗模式"></center>

节省功耗(最省电)效果:待机 > 停止 > 睡眠。

手册反复提到了事件和中断这两个词。

<strong><font color="#004a85">1、事件(WFI)和中断(WFE)的区别:</font> </strong>

事件:包括中断事件和非中断事件。

非中断事件:如GPIO电平变化,外设使能,初始化等不发生中断的事件。

中断事件:例如按键,按下按键会引起GPIO电平的变化(非中断事件)。若把按键配置为外部中断,即把非中断事件变成中断事件。中断是发生中断事件后执行对应的xxx_IRQHandler()中断服务函数。

详细原理框图可以看STM32F4XX英文参考手册的Figure 41. External interrupt/event controller block diagram

<strong><font color="#004a85">2、睡眠模式</font> </strong>

<strong>2.1、手册</strong>

<center><img src="http://mcu.eetrend.com/files/2021-11/博客/100555157-226405-2.png&quot; alt=“STM32MX电源管理低功耗模式"></center>
<center><img src="http://mcu.eetrend.com/files/2021-11/博客/100555157-226406-3.png&quot; alt=“STM32MX电源管理低功耗模式"></center>

注意:睡眠模式下,无论设置事件(WFI)和中断(WFE),系统时钟SysTick_Handler()都能将其唤醒。

<strong>2.2、软件步骤(粗体是必做步骤):</strong>

1、进入睡眠前可以降低或者关闭外设的时钟速度达到更好的效果(唤醒后要恢复外设时钟)。

2、失能系统时钟SysTick_Handler()中断。

3、设置唤醒方式,进入睡眠模式(CPU时钟关闭,内核停止,对其他时钟和ADC时钟无影响,不改变GPIO管脚状态)。

4、唤醒方式:任意中断唤醒或者事件(具体看你设置的唤醒方式)

5、唤醒延时:无

6、唤醒之后:使能系统时钟SysTick_Handler()中断(唤醒后要恢复外设时钟)。

7、程序继续运行。

<strong>2.3、代码:</strong>

<pre style="overflow-x:auto; background-color:#e9e9e9;">/**
* @brief This function configures the system to enter Sleep mode for
* current consumption measurement purpose.
* Sleep Mode
* ==========
* - System Running at PLL
* - Flash 5 wait state
* - Instruction and Data caches ON
* - Prefetch ON
* - Code running from Internal FLASH
* - All peripherals disabled.
* - Wakeup using EXTI Line (USER Button)
* @param None
* @retval None
*/
void SleepMode_Measure(void)
{
//挂起(暂停)系统时钟中断
HAL_SuspendTick();

/* 进入睡眠模式, 任意中断唤醒 */
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);

/* 恢复系统时钟中断 */
HAL_ResumeTick();

/* Add a delay of 200ms after exit from Sleep mode */
HAL_Delay(200);
}</pre>

<strong><font color="#004a85">3、停止模式</font> </strong>

<strong>3.1、手册</strong>

<center><img src="http://mcu.eetrend.com/files/2021-11/博客/100555157-226407-4.png&quot; alt=“STM32MX电源管理低功耗模式"></center>
<center><img src="http://mcu.eetrend.com/files/2021-11/博客/100555157-226408-5.png&quot; alt=“STM32MX电源管理低功耗模式"></center>

<strong>3.2、软件步骤(粗体是必做步骤):</strong>

1、进入睡眠前可以降低或者关闭外设的时钟速度达到更好的效果(唤醒后要恢复外设时钟)。

2、芯片内部FLASH掉电。

3、设置唤醒方式:_WFI 或者 _WFE,(RTC闹钟中断也可以唤醒,后面说)

4、关闭电压调节器(电压调节器是动态调节芯片内部电压,关闭后更加节省功耗,但是唤醒时间加长)

5、进入停止模式:所有的1.2V时钟都关闭(HSI和HSE的振荡器关闭,不改变GPIO管脚状态)。

6、唤醒方式:任意外部中断 或者 RTC闹钟

7、唤醒延时:有,(关闭电压调节器唤醒时间更长)。

8、唤醒之后:重新初始化时钟。

9、程序继续运行。

<strong>3.3、代码:</strong>

下面有两个停止模式函数StopMode_Measure()和StopUnderDriveMode_Measure();

前者是没有关闭电压调节器的,后者是关闭了电压调节器的,但是唤醒时间加长。

两个函数都RTC闹钟定时了20s唤醒。若不喜欢用RTC删除即可。

<pre style="overflow-x:auto; background-color:#e9e9e9;">extern void SystemClock_Config(void); //外部链接用户初始化时钟

/**
* @brief This function configures the system to enter Stop mode with RTC
* clocked by LSE or LSI for current consumption measurement purpose.
* STOP Mode with RTC clocked by LSE/LSI
* =====================================
* - RTC Clocked by LSE or LSI
* - Regulator in LP mode
* - HSI, HSE OFF and LSI OFF if not used as RTC Clock source
* - No IWDG
* - FLASH in deep power down mode
* - Automatic Wakeup using RTC clocked by LSE/LSI (~20s)
* @param None
* @retval None
*
* @note
* 此函数 没有关闭电压调节器
*
*/
void StopMode_Measure(void)
{
RTCHandle.Instance = RTC;

RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24;
RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

if(HAL_RTC_Init(&RTCHandle) != HAL_OK)
{
Error_Handler();
}

/*## 配置RTC唤醒 20s唤醒 ###########################################*/
HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16);

/* flash进入掉电 */
HAL_PWREx_EnableFlashPowerDown();

/*进入停止模式, 外部中断唤醒或者RTC闹钟唤醒 */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

//重新初始化时钟
SystemClock_Config();

/* Disable Wake-up timer */
if(HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
}

/**
* @brief This function configures the system to enter in Under-Drive stop mode with RTC
* clocked by LSE or LSI for current consumption measurement purpose.
* STOP Mode with RTC clocked by LSE/LSI
* =====================================
* - RTC Clocked by LSE or LSI
* - Regulator in LP mode
* - Under drive feature enabled
* - HSI, HSE OFF and LSI OFF if not used as RTC Clock source
* - No IWDG
* - FLASH in deep power down mode
* - Automatic Wakeup using RTC clocked by LSE/LSI (~20s)
* @param None
* @retval None
*
* @note
* 此函数 关闭电压调节器 ,唤醒需要的时间更长,但是功耗理论更小
*
*/
void StopUnderDriveMode_Measure(void)
{
RTCHandle.Instance = RTC;

/* Configure RTC prescaler and RTC data registers as follow:
- Hour Format = Format 24
- Asynch Prediv = Value according to source clock
- Synch Prediv = Value according to source clock
- OutPut = Output Disable
- OutPutPolarity = High Polarity
- OutPutType = Open Drain */
RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24;
RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

if(HAL_RTC_Init(&RTCHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}

/*## Configure the Wake up timer ###########################################*/
/* RTC Wakeup Interrupt Generation:
Wakeup Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI))
Wakeup Time = Wakeup Time Base * WakeUpCounter
= (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI)) * WakeUpCounter
==> WakeUpCounter = Wakeup Time / Wakeup Time Base
To configure the wake up timer to 20s the WakeUpCounter is set to 0xA017:
RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
Wakeup Time Base = 16 /(~32.768KHz) = ~0,488 ms
Wakeup Time = ~20s = 0,488ms * WakeUpCounter
==> WakeUpCounter = ~20s/0,488ms = 40983 = 0xA017 */
HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16);

/* FLASH Deep Power Down Mode enabled */
HAL_PWREx_EnableFlashPowerDown();

/* Enter under-drive Stop Mode */
HAL_PWREx_EnterUnderDriveSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

/* Configures system clock after wake-up from STOP: enable HSE, PLL and select
PLL as system clock source (HSE and PLL are disabled in STOP mode) */
// SYSCLKConfig_STOP();
SystemClock_Config();

/* Disable Wake-up timer */
if(HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
}</pre>

<strong><font color="#004a85">4、待机模式</font> </strong>

<strong>4.1、手册</strong>

<center><img src="http://mcu.eetrend.com/files/2021-11/博客/100555157-226409-6.png&quot; alt=“STM32MX电源管理低功耗模式"></center>
<center><img src="http://mcu.eetrend.com/files/2021-11/博客/100555157-226410-7.png&quot; alt=“STM32MX电源管理低功耗模式"></center>
<center><img src="http://mcu.eetrend.com/files/2021-11/博客/100555157-226411-8.png&quot; alt=“STM32MX电源管理低功耗模式"></center>

<strong>4.2、软件步骤(粗体是必做步骤):</strong>

1、是否允许访问备份区

2、是否备份区使用RTC(用于唤醒)

3、设置唤醒方式:WKUP 引脚上升沿、 RTC 闹钟(闹钟 A 和闹钟 B)、 RTC 唤醒事件、 RTC入侵事件、 RTC 时间戳事件、 NRST 引脚外部复位 和 IWDG 复位。

4、进入待机模式:关闭1.2V所有时钟,HSI和HSE的振荡器关闭,电压调节器关闭。

5、唤醒延时:有

6、唤醒之后:复位程序(和按下复位键效果一致)

<strong>4.3、代码:</strong>

<pre style="overflow-x:auto; background-color:#e9e9e9;">/**
* @brief This function configures the system to enter Standby mode for
* current consumption measurement purpose.
* STANDBY Mode
* ============
* - Backup SRAM and RTC OFF
* - IWDG and LSI OFF
* - Wakeup using WakeUp Pin (PA.00)
* @param None
* @retval None
*/
void StandbyMode_Measure(void)
{
/* Enable Power Clock*/
__HAL_RCC_PWR_CLK_ENABLE();

/* Allow access to Backup */
HAL_PWR_EnableBkUpAccess();

/* Reset RTC Domain */
__HAL_RCC_BACKUPRESET_FORCE();
__HAL_RCC_BACKUPRESET_RELEASE();

/* Disable all used wakeup sources: Pin1(PA.0) */
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);

/* Clear all related wakeup flags */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

/* Re-enable all used wakeup sources: Pin1(PA.0) */
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);

/* Request to enter STANDBY mode */
HAL_PWR_EnterSTANDBYMode();
}

/**
* @brief This function configures the system to enter Standby mode with RTC
* clocked by LSE or LSI for current consumption measurement purpose.
* STANDBY Mode with RTC clocked by LSE/LSI
* ========================================
* - RTC Clocked by LSE/LSI
* - IWDG OFF
* - Backup SRAM OFF
* - Automatic Wakeup using RTC clocked by LSE/LSI (after ~20s)
* @param None
* @retval None
*/
void StandbyRTCMode_Measure(void)
{
RTCHandle.Instance = RTC;
/* Configure RTC prescaler and RTC data registers as follow:
- Hour Format = Format 24
- Asynch Prediv = Value according to source clock
- Synch Prediv = Value according to source clock
- OutPut = Output Disable
- OutPutPolarity = High Polarity
- OutPutType = Open Drain */
RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24;
RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

if(HAL_RTC_Init(&RTCHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}

/*## Configure the Wake up timer ###########################################*/
/* RTC Wakeup Interrupt Generation:
Wakeup Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI))
Wakeup Time = Wakeup Time Base * WakeUpCounter
= (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI)) * WakeUpCounter
==> WakeUpCounter = Wakeup Time / Wakeup Time Base
To configure the wake up timer to 20s the WakeUpCounter is set to 0xA017:
RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
Wakeup Time Base = 16 /(~32.768KHz) = ~0,488 ms
Wakeup Time = ~20s = 0,488ms * WakeUpCounter
==> WakeUpCounter = ~20s/0,488ms = 40983 = 0xA017 */
/* Disable Wake-up timer */
if(HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}

/*## Clear all related wakeup flags ########################################*/
/* Clear PWR wake up Flag */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

/* Clear RTC Wake Up timer Flag */
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RTCHandle, RTC_FLAG_WUTF);

/*## Setting the Wake up time ##############################################*/
HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16);

/*## Enter the Standby mode ################################################*/
/* Request to enter STANDBY mode */
HAL_PWR_EnterSTANDBYMode();
}

/**
* @brief This function configures the system to enter Standby mode with RTC
* clocked by LSE or LSI and with Backup SRAM ON for current consumption
* measurement purpose.
* STANDBY Mode with RTC clocked by LSE/LSI and BKPSRAM
* ====================================================
* - RTC Clocked by LSE or LSI
* - Backup SRAM ON
* - IWDG OFF
* - Automatic Wakeup using RTC clocked by LSE/LSI (after ~20s)
* @param None
* @retval None
*/
void StandbyRTCBKPSRAMMode_Measure(void)
{
/* Configure RTC prescaler and RTC data registers as follow:
- Hour Format = Format 24
- Asynch Prediv = Value according to source clock
- Synch Prediv = Value according to source clock
- OutPut = Output Disable
- OutPutPolarity = High Polarity
- OutPutType = Open Drain */
RTCHandle.Instance = RTC;
RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24;
RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

if(HAL_RTC_Init(&RTCHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}

/*## Configure the Wake up timer ###########################################*/
/* RTC Wakeup Interrupt Generation:
Wakeup Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI))
Wakeup Time = Wakeup Time Base * WakeUpCounter
= (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI)) * WakeUpCounter
==> WakeUpCounter = Wakeup Time / Wakeup Time Base
To configure the wake up timer to 20s the WakeUpCounter is set to 0xA017:
RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
Wakeup Time Base = 16 /(~32.768KHz) = ~0,488 ms
Wakeup Time = ~20s = 0,488ms * WakeUpCounter
==> WakeUpCounter = ~20s/0,488ms = 40983 = 0xA017 */
/* Disable Wake-up timer */
if(HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}

/*## Clear all related wakeup flags ########################################*/
/* Clear PWR wake up Flag */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

/* Clear RTC Wake Up timer Flag */
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RTCHandle, RTC_FLAG_WUTF);

/*## Setting the Wake up time ##############################################*/
HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0xA017, RTC_WAKEUPCLOCK_RTCCLK_DIV16);

/* Enable BKPRAM Clock */
__HAL_RCC_BKPSRAM_CLK_ENABLE();

/* Enable the Backup SRAM low power Regulator */
HAL_PWREx_EnableBkUpReg();

/*## Enter the Standby mode ################################################*/
/* Request to enter STANDBY mode */
HAL_PWR_EnterSTANDBYMode();
}</pre>

<strong><font color="#004a85">5、RTC闹钟唤醒</font> </strong>

<strong>5.1、手册</strong>

<center><img src="http://mcu.eetrend.com/files/2021-11/博客/100555157-226412-9.png&quot; alt=“STM32MX电源管理低功耗模式"></center>

RTC唤醒代码,上面停止和待机模式都有。
————————————————
版权声明:本文为CSDN博主「sudaroot」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sudaroot/article/details/85626218