STM32 Voltage Scaling
Introduction
Voltage scaling is a powerful technique in STM32 microcontrollers that allows you to adjust the operating voltage of the CPU and other digital peripherals to optimize power consumption. By reducing the voltage supplied to these components when maximum performance isn't needed, you can significantly extend battery life in portable applications or reduce energy consumption in mains-powered devices.
This technique is particularly valuable for battery-powered IoT devices, wearables, sensor nodes, and any application where power efficiency is a priority. In this tutorial, we'll explore how voltage scaling works in STM32 microcontrollers, when to use it, and how to implement it in your projects.
Understanding Voltage Scaling
What is Voltage Scaling?
Voltage scaling refers to the ability to dynamically adjust the operating voltage of the CPU and digital peripherals. The fundamental principle is simple: lower operating voltage leads to lower power consumption, following the power equation:
Where:
- P is power consumption
- C is capacitance (fixed for a given device)
- V is voltage
- f is frequency
Note that power consumption scales quadratically with voltage, making voltage reduction a highly effective way to save energy.
Voltage Scaling in STM32
STM32 microcontrollers typically offer multiple voltage scaling modes, which are often labeled as:
- Range 1: Highest performance, highest power consumption
- Range 2: Medium performance, reduced power consumption
- Range 3: Lowest performance, lowest power consumption
The specific ranges and their exact implications vary between STM32 families. For example:
Let's look at how voltage scaling ranges affect the STM32L4 series as an example:
Voltage Range | Max CPU Frequency | Relative Power | Use Case |
---|---|---|---|
Range 1 | 80 MHz | Highest | Performance-critical tasks |
Range 2 | 26 MHz | Medium | Balanced performance/power |
Range 3 | 2 MHz | Lowest | Ultra-low-power scenarios |
Implementation Guide
Now, let's explore how to implement voltage scaling in your STM32 projects.
Prerequisites
Before using voltage scaling:
- Understand your application's performance requirements
- Be aware of how frequency limits change with voltage scaling
- Have STM32CubeIDE or equivalent setup with the appropriate HAL libraries
Basic Implementation
Here's how to configure voltage scaling using the HAL library in STM32CubeIDE:
/* Configure the main internal regulator output voltage */
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); // Highest performance
// Or for lower power consumption:
// HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);
// Or for lowest power (with reduced max frequency):
// HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE3);
This code is typically placed in the system clock configuration function.
Complete Example: Dynamic Voltage Scaling
Let's create a more comprehensive example that dynamically switches between voltage scaling levels based on processing needs:
#include "main.h"
/* Private function prototypes */
void SystemClock_Config(void);
void ConfigureVoltageScaling(uint32_t VoltageScaling);
void PerformLightTask(void);
void PerformHeavyTask(void);
int main(void)
{
/* Reset of all peripherals, initialize the Flash interface and the Systick */
HAL_Init();
/* Configure the system clock for high performance */
SystemClock_Config();
/* Initialize LED */
BSP_LED_Init(LED2);
while (1)
{
/* For light processing tasks, use lower voltage */
ConfigureVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);
PerformLightTask();
/* For heavy processing tasks, use higher voltage */
ConfigureVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
PerformHeavyTask();
/* Return to low power */
ConfigureVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);
/* Blink LED to indicate cycle completion */
BSP_LED_Toggle(LED2);
HAL_Delay(1000);
}
}
/**
* @brief Configure voltage scaling
* @param VoltageScaling: The desired voltage scaling level
* @retval None
*/
void ConfigureVoltageScaling(uint32_t VoltageScaling)
{
/* Switch to the required voltage scaling mode */
HAL_PWREx_ControlVoltageScaling(VoltageScaling);
/* Wait for voltage scaling to complete */
while(PWR->SR2 & PWR_SR2_VOSF) {}
}
/**
* @brief Perform a light processing task
* @retval None
*/
void PerformLightTask(void)
{
/* Simple task that doesn't need full CPU performance */
uint32_t i;
volatile uint32_t dummy = 0;
for(i = 0; i < 10000; i++)
{
dummy++;
}
}
/**
* @brief Perform a heavy processing task
* @retval None
*/
void PerformHeavyTask(void)
{
/* Complex task that requires higher performance */
uint32_t i;
volatile uint32_t dummy = 0;
for(i = 0; i < 1000000; i++)
{
dummy = (dummy * 1103515245 + 12345) % 0x7FFFFFFF;
}
}
Important Considerations
When implementing voltage scaling, keep these points in mind:
-
Clock Frequency Limitations: Each voltage range has a maximum allowed clock frequency. Exceeding this can cause unpredictable behavior.
-
Transition Time: Changing voltage scaling levels isn't instantaneous. Always check the VOSF (Voltage Scaling Flag) in the PWR_SR2 register to ensure the transition is complete.
-
Peripheral Behavior: Some peripherals may have different timing characteristics at lower voltage levels. Consult the datasheet for details.
-
Flash Access Time: You may need to adjust flash wait states when changing voltage scaling levels.
Real-World Applications
Let's explore some practical applications of voltage scaling: