Low Power Modes in STM32 – Power Consumption, Sleep, Stop, and Standby Explained
STM32 microcontrollers offer multiple low power modes that can drastically reduce power consumption in embedded systems. In this guide, we’ll break down Sleep, Stop, and Standby modes, show you how to enter and exit each mode, and examine how they impact real-world power consumption—especially on boards like the STM32 Blue Pill. Whether you’re building an IoT device or comparing low power microcontrollers, this tutorial provides practical insights and tested code examples.

By default, the STM32 microcontroller enters Run mode following a system reset or power-on reset. In this mode, the CPU is driven by the HCLK clock signal, and the program code is actively executed.
STM32 microcontrollers offer multiple low-power modes designed to reduce power consumption during periods when the CPU is not required to operate—for instance, while waiting for an external interrupt or event. In this tutorial, we will explore these low-power modes in detail.
STM32 supports the following three low-power modes:
- Sleep Mode – The CPU (including the FPU core) is halted, while all peripherals continue to operate.
- Stop Mode – All internal clocks are halted, significantly reducing power usage while retaining RAM and register contents.
- Standby Mode – The 1.2V domain is powered off, resulting in the lowest power consumption. Most internal state is lost except for data retained in Backup SRAM or powered by VBAT.
STM32 Low Power Modes Explained
STM32 microcontrollers are designed with energy efficiency in mind, offering several low power modes to minimize current consumption during idle or inactive periods. These modes allow developers to optimize power usage depending on the application’s requirements, particularly in battery-powered or energy-sensitive systems.
The three main low power modes available in STM32 are:
- Sleep Mode
In Sleep mode, the CPU is halted while all peripheral clocks continue to run. This allows peripherals like timers, USART, or ADCs to remain active, enabling the MCU to quickly resume operation on an interrupt. It’s ideal for short, low-latency power-saving scenarios. - Stop Mode
Stop mode offers deeper power savings by disabling all clocks, including the system clock, while retaining the contents of RAM and registers. The regulator can be set in either main or low-power mode, and the MCU can be awakened through external interrupts, RTC, or other events. This mode is well-suited for applications with periodic wake-up requirements. - Standby Mode
Standby mode provides the lowest power consumption. In this mode, the 1.2V domain is powered off, most peripherals and internal memory are lost (except for data in Backup SRAM or RTC powered by VBAT). The MCU resumes from a reset after wake-up. This mode is ideal for ultra-low-power applications where the device remains off for extended periods.
STM32 Power Consumption in Sleep, Stop, and Standby Modes
The power savings in STM32 depend on the selected mode and voltage regulator settings. Here’s a rough comparison for STM32F103 (Blue Pill) at 3.3V supply:
Mode | Current Draw (typical) | Wake-up Time | Retains RAM? | Use Case |
Sleep | ~2–5 mA | Fast | Yes | Short idle time, timer active |
Stop | ~20–100 µA | Medium | Yes | Periodic wake, sensor sleep |
Standby | ~1–5 µA | Slow | No | Battery-powered deep sleep apps |
You can measure this using an ammeter in series with VDD or use ST-Link power monitor in STM32CubeIDE.
SLEEP MODE
I will first start with the simplest one, which is the SLEEP MODE. In this mode, CPU CLK is turned OFF and there is no effect on other clocks or analog clock sources. The current consumption is HIGHEST in this mode, compared to other Low Power Modes.
Entering into the Sleep Mode
In order to enter the SLEEP MODE, we must disable the systick interrupt first, or else this interrupt will wake the MCU every time the interrupt gets triggered.
HAL_SuspendTick(); // Disable the Intrrupt
Next, we will enter the sleep mode by executing the WFI (Wait For Interrupt), or WFE (Wait For Event) instructions. If the WFI instruction was used to enter the SLEEP MODE, any peripheral interrupt acknowledged by the NVIC can wake up the device.
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
Wakeup from the Sleep Mode
As mentioned above, I have entered the SLEEP MODE using the WFI instruction, so the device will wakeup whenever any interrupt is triggered.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
HAL_ResumeTick();
}
Inside the callback function we can resume the systick, so that we can use the delay function again for the rest of the code.
SLEEPONEXIT
This is another feature available in SLEEP MODE, where the MCU will wake up when the interrupt is triggered, it will process the ISR, and go back to sleep when the ISR exits. This is useful when we want the controller to run only in the interrupt mode.
HAL_PWR_EnableSleepOnExit ();
The above function must be called before going into the SLEEP MODE to activate the sleeponexit feature. We can disable it by calling
HAL_PWR_DisableSleepOnExit ();
The Full Code
The entire code for the SLEEP MODE, with SLEEPONEXIT feature is shown below
uint8_t Rx_data;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
HAL_UART_Receive_IT(huart, &Rx_data, 1);
str = "WakeUP from SLEEP by UART\r\n";
HAL_UART_Transmit(&huart2, (uint8_t *)str, strlen (str), HAL_MAX_DELAY);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
str = "WakeUP from SLEEP by EXTI\r\n";
HAL_UART_Transmit(&huart2, (uint8_t *)str, strlen (str), HAL_MAX_DELAY);
HAL_PWR_DisableSleepOnExit ();
}
int main ()
{
......
......
HAL_UART_Receive_IT(&huart2, &Rx_data, 1);
while (1)
{
str = "Going into SLEEP MODE in 5 seconds\r\n";
HAL_UART_Transmit(&huart2, (uint8_t *)str, strlen (str), HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 1);
HAL_Delay(5000);
/* 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();
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, 0); // Just to indicate that the sleep mode is activated
HAL_PWR_EnableSleepOnExit ();
// Enter Sleep Mode , wake up is done once User 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();
str = "WakeUP from SLEEP\r\n";
HAL_UART_Transmit(&huart2, (uint8_t *)str, strlen (str), HAL_MAX_DELAY);
for (int i=0; i<20; i++)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(100);
}
}
}
Result
Below is the result of the above code.
Basically, when the MCU wakes up because of the UART interrupt, it goes back to sleep after processing the ISR (i.e after printing the string), but when it wakes up due to the EXTI, the SLEEPONEXIT is disabled, and rest of the main function is executed as usual.
Video
Below is the full video explaining the Sleep Mode.
Check out the Video Below
STOP MODE
In Stop mode, all clocks in the 1.2 V domain are stopped, the PLLs, the HSI and the HSE RC oscillators are disabled. Internal SRAM and register contents are preserved. STOP MODE have may different categories depending on what should be turned off. Below is the picture from the STM32F446RE reference manual
Entering the Stop Mode
Just like sleep mode, In order to enter the STOP MODE, we must disable the systick interrupt, or else this interrupt will wake the MCU every time the interrupt gets triggered.
HAL_SuspendTick(); // disable interrupt
Next, we will enter the sleep mode by executing the WFI (Wait For Interrupt), or WFE (Wait For Event) instructions. If the WFI instruction was used to enter the STOP MODE, EXTI, Independent watchdog (IWDG), or RTC can wake up the device. Also I am using the first mode as shown in the picture above i.e. The main Regulator will be turned off and only the LOW Power Regulator will be running.
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
Wakeup from Stop Mode
As mentioned above, I have entered the STOP MODE using the WFI instruction, so the device will wakeup whenever any interrupt is triggered by an EXTI, Independent watchdog (IWDG), or RTC.
We must reconfigure the SYSTEM CLOCKS after wakeup, as they were disabled when entering the STOP MODE. Also don’t forget to resume the systick.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_13)
{
SystemClock_Config ();
HAL_ResumeTick();
}
}
SLEEPONEXIT
SleeponExit works the same way as it does for the SLEEP mode. You can check the implementation above under the SLEEP mode.
The Full Code
The entire code for STOP MODE is as shown below
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
SystemClock_Config ();
HAL_ResumeTick();
char *str = "WAKEUP FROM RTC\n NOW GOING IN STOP MODE AGAIN\n\n";
HAL_UART_Transmit(&huart2, (uint8_t *) str, strlen (str), HAL_MAX_DELAY);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_13)
{
SystemClock_Config ();
HAL_ResumeTick();
char *str = "WAKEUP FROM EXTII\n\n";
HAL_UART_Transmit(&huart2, (uint8_t *) str, strlen (str), HAL_MAX_DELAY);
HAL_PWR_DisableSleepOnExit();
}
}
int main ()
{
.......
.......
.......
/*## Configure the Wake up timer ###########################################*/
/* RTC Wake-up Interrupt Generation:
Wake-up Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI))
==> WakeUpCounter = Wake-up Time / Wake-up Time Base
To configure the wake up timer to 20s the WakeUpCounter is set to 0xA017:
RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
Wake-up Time Base = 16 /(32KHz) = 0.0005 seconds
==> WakeUpCounter = ~10s/0.0005s = 20000 = 0x4E20 */
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0x4E20, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
/****** Suspend the Ticks before entering the STOP mode or else this can wake the device up **********/
HAL_SuspendTick();
HAL_PWR_EnableSleepOnExit();
/* Enter Stop Mode */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
for (int i=0; i<10; i++)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(1000);
}
while (1)
{
.....
}
}
Result
The RTC Setup is very long, and it is explained in the VIDEO. DO check the video below to understand it.
When the MCU enters the STOP MODE, it can be woken up by either RTC periodic trigger, or by EXTI line. When the former wakes the MCU, the interrupt is processed, where it will print the string, and than goes back in the STOP MODE. Whereas, when the EXTI line wakes the device, the sleeponexit will be disabled, and the main loop will run.
Video
Check out the Video Below
STANDBY MODE
The Standby mode allows to achieve the lowest power consumption. It is based on the Cortex®-M4 with FPU deep-sleep mode, with the voltage regulator disabled. The 1.2 V domain is consequently powered off. The PLLs, the HSI oscillator and the HSE oscillator are also switched off.
Entering Standby Mode
Before entering the STANDBY MODE, we must disable the wakeup flags as shown below
/* Clear the WU FLAG */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
/* clear the RTC Wake UP (WU) flag */
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
Next, enable the wakeup pin, or the RTC periodic wakeup (if you want to use RTC)
/* Enable the WAKEUP PIN */
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
/* enable the RTC Wakeup */
/* RTC Wake-up Interrupt Generation:
Wake-up Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI))
==> WakeUpCounter = Wake-up Time / Wake-up Time Base
To configure the wake up timer to 5s the WakeUpCounter is set to 0x2710:
RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
Wake-up Time Base = 16 /(32KHz) = 0.0005 seconds
==> WakeUpCounter = ~5s/0.0005s = 20000 = 0x2710
*/
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0x2710, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
{
Error_Handler();
}
Finally enter the STANDBY MODE
HAL_PWR_EnterSTANDBYMode();
Wakeup from Standby Mode
The standby wakeup is same as a system RESET. The entire code runs from the beginning just as if it was a RESET. The only difference between a reset and a STANDBY wakeup is that, when the MCU wakesup, The SBF status flag in the PWR power control/status register (PWR_CSR) is set. The wakeup can be triggered by WKUP pin rising edge, RTC alarm (Alarm A and Alarm B), RTC wakeup, tamper event, time stamp event, external reset in NRST pin, IWDG reset.
The Full Code
The entire code for the STANDBY MODE is as shown below
int main ()
{
..............
.............
if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)
{
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB); // clear the flag
/** display the string **/
char *str = "Wakeup from the STANDBY MODE\n\n";
HAL_UART_Transmit(&huart2, (uint8_t *)str, strlen (str), HAL_MAX_DELAY);
/** Blink the LED **/
for (int i=0; i<20; i++)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(200);
}
/** Disable the WWAKEUP PIN **/
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); // disable PA0
/** Deactivate the RTC wakeup **/
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
}
/** Now enter the standby mode **/
/* Clear the WU FLAG */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
/* clear the RTC Wake UP (WU) flag */
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
/* Display the string */
char *str = "About to enter the STANDBY MODE\n\n";
HAL_UART_Transmit(&huart2, (uint8_t *)str, strlen (str), HAL_MAX_DELAY);
/* Blink the LED */
for (int i=0; i<5; i++)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_Delay(750);
}
/* Enable the WAKEUP PIN */
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
/* enable the RTC Wakeup */
/* RTC Wake-up Interrupt Generation:
Wake-up Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSI))
==> WakeUpCounter = Wake-up Time / Wake-up Time Base
To configure the wake up timer to 5s the WakeUpCounter is set to 0x2710:
RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
Wake-up Time Base = 16 /(32KHz) = 0.0005 seconds
==> WakeUpCounter = ~5s/0.0005s = 20000 = 0x2710
*/
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0x2710, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
{
Error_Handler();
}
/* one last string to be sure */
char *str2 = "STANDBY MODE is ON\n\n";
HAL_UART_Transmit(&huart2, (uint8_t *)str2, strlen (str2), HAL_MAX_DELAY);
/* Finally enter the standby mode */
HAL_PWR_EnterSTANDBYMode();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Result
Video
Check out the Video Below
Low Power MCU Comparison – Is STM32 the Best?
STM32 MCUs offer great balance between performance and power efficiency, but they’re not the only option. Here’s a quick comparison with other low power MCUs:
MCU | Sleep Current | Standby Current | Notes |
STM32F1 (Blue Pill) | ~2–5 mA | ~1–5 µA | Great for hobbyists, full STM32 HAL support |
STM32L0/L4 Series | ~500 nA | ~50 nA | Ultra-low power with aggressive optimizations |
ATmega328 (Arduino Uno) | ~1.5 mA | ~200 µA | Easy to use but not as efficient |
nRF52 (Nordic) | ~1.8 µA | ~400 nA | BLE-ready, extremely power-efficient |
If your project demands extended battery life, STM32L-series or nRF52 may be more suitable.
These low power modes are especially important when working with low power microcontrollers like the STM32 Blue Pill, where power consumption must be minimized. By testing each mode, developers can decide which best suits their battery-operated or IoT designs. STM32 makes it simple to toggle modes while keeping your code portable and efficient.
PROJECT DOWNLOAD
Info
You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.
STM32 Low Power Modes FAQs
STM32 typically supports Sleep, Stop, and Standby modes — each offering increasing levels of power saving at the cost of slower wake-up and reduced peripheral availability.
The CPU core is stopped while peripherals remain active. This mode offers the fastest wake-up time (sub-microsecond) but moderate power savings.
Stop mode stops the CPU and most clocks but retains SRAM and register contents. It uses lower power than Sleep, allows wake-up from RTC or EXTI, and has reasonable wake-up latency (~microseconds).
Standby mode achieves the lowest power consumption by powering off core regulators and most clocks. It resets the MCU on wake-up (similar to a reset), retaining only RTC or backup SRAM if configured.
-> Sleep mode: wakes instantly via interrupts
-> Stop mode: wakes from RTC, EXTI, or watchdog
-> Standby mode: wakes only from RTC alarms, wake-up pins, or reset-like events.
🙏 Support Us by Disabling Adblock
We rely on ad revenue to keep Controllerstech free and regularly updated. If you enjoy the content and find it helpful, please consider whitelisting our website in your ad blocker.
We promise to keep ads minimal and non-intrusive.
Thank you for your support! 💙
In stm32f103c8t6 how can we exit from stand by mode using Auto wake up. can u please make a video on that?
using the RTC Alarm. It is already explained in the tutorial.
Hello , isue a dual-core st ( stm32h7) i need put all system in standby mode , but i only use m4core. My m7 core don´t have app yet.
I use the hal function ( HAL_PWR_EnterStandbyMode), my consumption does not go down, which means that the system does not go to full standby..
how can i do?
For sleep mode, you use an arbitrary GPIO pin to wake up MCU. Can I use any pin to wake it up from standby mode?
Hi! Using this example is possible to standby minutes or hours?? Because I tried to change the time of the standby and it only works from 1-30 seconds
The definition of HAL_RTCEx_SetWakeUpTimer_IT function is as follows:
HAL_RTCEx_SetWakeUpTimer_IT (RTC_HandleTypeDef * hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock)
The “WakeUpCounter” is 32 bit variable, so you can’t input higher value than that.
You can adjust the clock and other things as mentioned in the comment section (where I have used this function) to set the time as per your need.
Thanks!
==> WakeUpCounter = ~5s/0.0005s = 20000 = 0x2710
????
==> WakeUpCounter = ~5s/0.0005s = 10000 = 0x2710
Hi. I boot with stm32L010C6Tx. I am in standby mode. While waiting in standby mode, it shows between 3.1 micro amps and 50 micro amps 50 microamps is too high, I can’t use it like this. . I turned off all peripherals. What else should I turn off? Why coul
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_LPUART1_UART_Init(void);
static void MX_I2C1_Init(void);
static void MX_ADC_Init(void);
static void MX_RTC_Init(void);
if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET) {
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
printf(“Wakeup from the STANDBY MODE\n\n”);
for (int i = 0; i < 20; i++) {
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(200);
}
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
}
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
printf(“About to enter the STANDBY MODE\n\n”);
for (int i = 0; i < 5; i++) {
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(750);
}
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0x5A55, RTC_WAKEUPCLOCK_RTCCLK_DIV16)
!= HAL_OK) {
Error_Handler();
}
printf(“STANDBY MODE is ON\n\n”);
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_13);
HAL_GPIO_DeInit(GPIOA, SDIO_Pin);
HAL_GPIO_DeInit(GPIOA,GPO3_Pin);
HAL_GPIO_DeInit(GPIOA,BUZZER_Pin);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
HAL_GPIO_DeInit(GPIOA, CSB_Pin);
HAL_GPIO_DeInit(GPIOA,FCSB_Pin);
HAL_GPIO_DeInit(GPIOA,SCLK_Pin);
HAL_UART_DeInit(&hlpuart1);
HAL_I2C_DeInit(&hi2c1);
HAL_ADC_DeInit(&hadc);
HAL_PWR_EnterSTANDBYMode();
Awesome explanation!
Thanks
I tried pay pal for donation but it failed. will try something else
Many thanks!
But, I tried to wakeup stm32L053 (nucleo stm32l053) from ALARM A and… nothing! Of course, I used the directives:
__HAL_RTC_ALARM_CLEAR_FLAG(&hrtc, RTC_FLAG_ALRAF);
__HAL_RTC_ALARMA_ENABLE(&hrtc)
before HAL_PWR_EnterSTANDBYMode().
(The line “if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0x2710, … ” was commented to eleminate effects of WakeUpTimer).
Why this problem appeared?
Thanks your time for your excellent explanation. I found some problem for the standby. Each time when turn on the MCU, it will print “wakeup from standby”, Actually it should not happen until enter standby then exit from standby mode. Also each time when wake up by Wakeup pin (rising PA0 ) it prints “wakeup from standby” twice. So far I haven’t found how to fix that.
that’s an unusual behavior. I would recommend that you debug your code. reset the mcu and step over each function. while doing so, check the contents of PWR_CSR register. The SBF bit is set when the mcu wakes up from standby. SO in case of reset, this shouldn’t be set.
stand_by modda 2mA e kadar düşüyor. vidyoda uA seviyelerinde görünüyor. kod aynı olduğu halde 2mA görüyorum. yardım edermisiniz
maybe urs is not entering the standby.. blink some LED before entering the sleep mode so that you can confirm this
Really nice work. You deserve for much more viewers :O