Introduction
Welcome to the next lesson in our Power Management module. In the previous session, you successfully refactored a power-hungry polling application into an efficient, interrupt-driven one using Sleep mode. You learned the importance of the "Wait For Interrupt" (WFI) strategy and how to manage the SysTick timer to prevent premature wake-ups.
Today, we will build directly on that foundation. Our goal is to place the MCU into both Sleep and Stop modes and wake it using an external interrupt (EXTI). You will implement both modes in code, learning the critical differences in their setup and, most importantly, the procedure required to recover from each state. This lesson will solidify your understanding of the practical trade-offs between different low-power states, a crucial skill for any firmware engineer.
1. Review: Implementing Sleep Mode with EXTI Wake-up
Let's begin with a quick practical review of Sleep mode. As you learned, in Sleep mode, only the CPU core is stopped, while peripherals and their clocks remain active. This allows for very fast wake-up times.

The process to enter Sleep mode and wake via an external interrupt (like a button press) follows these steps:
- Configure a GPIO pin as an input with an external interrupt (e.g.,
GPIO_MODE_IT_FALLING). - Enable the EXTI line's interrupt in the NVIC.
- In your main loop, suspend the SysTick timer to prevent it from waking the CPU every millisecond.
- Call the HAL function to enter Sleep mode.
- Upon wake-up (triggered by the EXTI), execution resumes. Re-enable the SysTick timer.
- The
HAL_GPIO_EXTI_Callback()function is where you can handle the interrupt-specific logic.
/* main.c */
// Inside your while(1) loop
printf("Entering Sleep Mode...\r\n");
HAL_Delay(10); // Ensure printf buffer is flushed
// 1. Suspend SysTick
HAL_SuspendTick();
// 2. Enter Sleep Mode (execution pauses here)
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
// ---- MCU WAKES UP HERE ----
// 3. Resume SysTick
HAL_ResumeTick();
printf("Woke up from Sleep Mode!\r\n");
// ... your post-wakeup logic ...
For a detailed video walkthrough of setting this up, please watch the following tutorial.
STM32 Sleep Mode Tutorial | Reduce MCU Power Consumption
This video from ControllersTech provides a clear, step-by-step guide to implementing Sleep mode on an STM32F103, the same family as your Blue Pill. It's a great practical refresher.
Watch the segment from 03:06 to 07:03. Focus on how the code implements the logic we just discussed: suspending the tick, entering sleep, and resuming the tick after the interrupt wakes the CPU.
2. Deeper Savings: Introducing Stop Mode
While Sleep mode is useful, Stop mode offers a much more significant reduction in power consumption. In Stop mode, the MCU powers down not only the CPU but also the main high-speed clock sources (HSI, HSE, and the PLL). However, the contents of the SRAM and all peripheral registers are preserved.
This deeper sleep comes with a crucial consequence: because the system clock source is turned off, it must be re-initialized upon wake-up.
The following article provides an excellent comparison and explains the technical details for both Sleep and Stop modes.
STM32 Low Power Modes: Sleep, Stop, and Standby Explained
The article 'STM32 Low Power Modes Explained' by ControllersTech is a valuable text resource. It details the API calls and the critical differences between the modes.
Please read two sections from this article: 'STM32 SLEEP MODE': Briefly review this section to reinforce your understanding of HAL_PWR_EnterSLEEPMode and the use of HAL_SuspendTick(). 'STM32 STOP Mode': Read this section carefully. Pay close attention to the paragraph under 'Wake-up from Stop Mode' which states that the system clocks are not automatically restored and you must reconfigure them. This is the key takeaway for this part of the lesson.
3. Implementing Stop Mode with EXTI Wake-up
The procedure for entering Stop mode is very similar to Sleep mode, but with two key differences: a different HAL function and the mandatory clock reconfiguration after waking up.
The steps are:
- Configure the GPIO and EXTI, just as before.
- Suspend the SysTick timer (
HAL_SuspendTick()). - Call
HAL_PWR_EnterSTOPMode(). Note the different parameters compared to the sleep function. - The MCU enters Stop mode. Execution pauses.
- When the EXTI fires, the MCU wakes up. The code execution resumes at the instruction immediately following
HAL_PWR_EnterSTOPMode(). - Crucially, you must immediately call
SystemClock_Config()to restore your HSI/HSE and PLL configuration. - After the clock is stable, you can resume the SysTick (
HAL_ResumeTick()).
/* main.c */
// Inside your while(1) loop
printf("Entering STOP Mode...\r\n");
HAL_Delay(10);
// 1. Suspend SysTick
HAL_SuspendTick();
// 2. Enter STOP Mode (execution pauses here)
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// ---- MCU WAKES UP HERE ----
// 3. CRITICAL: Reconfigure the System Clock
SystemClock_Config(); // This function was generated by CubeMX
// 4. Resume SysTick
HAL_ResumeTick();
printf("Woke up from STOP Mode!\r\n");
// ... your post-wakeup logic ...
The following video demonstrates this exact process. While it uses an STM32F4, the HAL functions and the core concepts—especially the need to reconfigure the clock—are identical, which is a testament to the portability of the STM32 HAL.
STM32 Stop Mode Tutorial | Save Power Efficiently
This 'STM32 Stop Mode Tutorial' from ControllersTech walks through the entire implementation. It explicitly highlights the clock reconfiguration step, which is the most important part of this section.
Watch the segment from 03:10 to 07:37. Observe how the code is structured and pay special attention to the sequence of events after the MCU wakes up from Stop mode: first SystemClock_Config(), then HAL_ResumeTick().
4. Hands-on Exercise: Implementing Stop Mode Wake-up
Now it's your turn to apply what you've learned.
Your Task:
Create a new STM32CubeIDE project for your Blue Pill board.
- Configure
PC13as aGPIO_Outputfor the onboard LED. - Configure a user button on pin
PA8as aGPIO_Inputwith a pull-up resistor and set its mode toGPIO_MODE_IT_FALLING. - Enable the corresponding EXTI interrupt in the NVIC (
EXTI line[9:5] interrupt). - Configure
USART1for communication (e.g., at 115200 baud) so you can useprintf. - In
main.c, write an application that:- Prints a "System Initialized" message.
- Enters an infinite
while(1)loop. - Inside the loop, it prints "Entering STOP Mode in 3 seconds...".
- Blinks the LED on
PC13three times with a 200ms delay between toggles. - Follows the sequence described in Section 3 to enter Stop mode.
- Upon waking (from the button press on
PA8), it should reconfigure the clock, resume the tick, print "Woke up from STOP mode!", and toggle the LED once to confirm. - The loop should then repeat, re-entering Stop mode.
You can find a complete project example that uses this exact logic in the following resource. It is a fantastic reference if you get stuck, as it provides the full main.c and explains each part.
Sleep Mode with Button Press Wake-Up
The article 'Sleep Mode with Button Press Wake-Up' from EWSkills provides a complete, project-based implementation. Despite the title, it actually uses STOP mode for better power savings and provides an excellent template for your exercise.
Use this resource as a guide. First, read the section 'STM32 Low-Power Modes Overview' to see the rationale for choosing Stop mode. Then, examine the code in the 'Enter Sleep Mode Function' and 'Main Firmware Logic' sections. Notice how the enterSleepMode function correctly implements Stop mode and restores the system on wake-up. This is the logic you need to implement.
A Note on Debugging: When the MCU enters Stop mode, the core and its debug circuitry are powered down. This will cause your ST-Link debugger to disconnect. You will not be able to use breakpoints or step through code that executes after entering a deep sleep state. This is normal. Rely on printf statements via UART and LED indicators to verify that your code is working as expected.
Conclusion
Congratulations! You have now implemented the two most common low-power modes on an STM32 microcontroller and can wake the system using an external interrupt. This is a fundamental skill for building battery-powered and power-efficient devices.
Key Takeaways:
- Sleep Mode: Simple to use, fast wake-up. Stops only the CPU. Peripherals remain active.
- Stop Mode: Offers significant power savings by stopping high-speed clocks. Requires a system clock reconfiguration (
SystemClock_Config()) upon wake-up. - The general sequence for both is: Suspend Tick -> Enter Low-Power Mode -> (Wake-up) -> Reconfigure Clock (for Stop only) -> Resume Tick.
- Debugging deep sleep modes requires indirect methods like UART logging, as the debug interface is often disabled.
Preview of the Next Lesson:
You've learned to save power when the device is idle. But what about when it's active? In our next lesson, we will explore techniques to disable unused peripheral clocks in the RCC to minimize power consumption even when the CPU is running. This practice, known as clock gating, is another essential tool in your power optimization toolkit.