1. 测量MCU基础功耗
任务定义
本案例面向STM32L0系列MCU(以STM32L071为例),完成基础功耗测量。目标是在最小系统配置下,分别测量MCU在运行模式(Run)与待机模式(Standby)下的电流消耗,并验证待机模式唤醒功能正常。测量结果用于建立该芯片的功耗基线,为后续低功耗优化提供对比依据。
硬件连接与测量拓扑
使用精密万用表(如Keysight 34461A)串联在MCU供电回路中测量电流。测量点位于3.3V电源输出与STM32L0开发板VDD引脚之间。板载LED、调试器供电等额外负载必须断开或跳线隔离,确保万用表读数仅为MCU及其必要外围电路(去耦电容、复位上拉电阻)的电流。
代码实现
固件逻辑:系统上电后运行在MSI 2.1MHz时钟,先执行一次简单的GPIO翻转循环(约5秒),随后进入Standby模式。Standby模式下,仅保留RTC唤醒功能(使用LSI时钟),PA0配置为外部复位唤醒源。代码通过宏MEASURE_MODE区分运行模式与待机模式测量。
// main.c - STM32L071 基础功耗测量固件
#include "stm32l0xx_hal.h"
/* 测量模式选择:
* 0 = 运行模式测量(GPIO翻转循环)
* 1 = 待机模式测量(5秒后进入Standby)
*/
#define MEASURE_MODE 1
void SystemClock_Config(void);
static void Enter_Standby(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef gpio = {0};
gpio.Pin = GPIO_PIN_5;
gpio.Mode = GPIO_MODE_OUTPUT_PP;
gpio.Pull = GPIO_NOPULL;
gpio.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &gpio);
#if (MEASURE_MODE == 0)
/* 运行模式测量:持续翻转GPIO,保持CPU活跃 */
while (1)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
for (volatile uint32_t i = 0; i < 100000; i++);
}
#else
/* 待机模式测量:5秒后进入Standby */
HAL_Delay(5000);
Enter_Standby();
/* 唤醒后复位重启,重新执行main */
#endif
}
static void Enter_Standby(void)
{
/* 使能PWR时钟 */
__HAL_RCC_PWR_CLK_ENABLE();
/* 清除唤醒标志 */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
/* 使能RTC唤醒功能(使用LSI时钟) */
__HAL_RCC_RTC_ENABLE();
__HAL_RCC_LSI_ENABLE();
while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET);
RTC_HandleTypeDef hrtc = {0};
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
HAL_RTC_Init(&hrtc);
/* 配置RTC唤醒定时器:LSI约37kHz,设置约1秒周期 */
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 37000, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
/* 使能待机模式 */
HAL_PWR_EnableSleepOnExit();
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
/* 进入Standby模式 */
HAL_PWR_EnterSTANDBYMode();
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef osc = {0};
RCC_ClkInitTypeDef clk = {0};
/* 使用MSI 2.1MHz作为系统时钟 */
osc.OscillatorType = RCC_OSCILLATORTYPE_MSI;
osc.MSIState = RCC_MSI_ON;
osc.MSIClockRange = RCC_MSIRANGE_5; // 约2.1MHz
osc.MSICalibrationValue = 0;
HAL_RCC_OscConfig(&osc);
clk.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
clk.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
clk.AHBCLKDivider = RCC_SYSCLK_DIV1;
clk.APB1CLKDivider = RCC_HCLK_DIV1;
clk.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_0);
}
void SysTick_Handler(void)
{
HAL_IncTick();
}
void RTC_WAKEUP_IRQHandler(void)
{
HAL_RTCEx_WakeUpTimerIRQHandler(&hrtc);
}
工程配置与编译
使用STM32CubeIDE 1.10+创建STM32L071RBTx工程,将上述代码替换main.c。在stm32l0xx_hal_conf.h中确保已启用HAL_RTC_MODULE_ENABLED和HAL_PWR_MODULE_ENABLED。编译优化等级设置为-O0(运行模式测量时避免编译器优化掉延时循环)。
测量步骤与判定标准
| 步骤 | 操作 | 观测与判定 |
|---|---|---|
| 1 | 将MEASURE_MODE设为0,编译烧录,万用表置于mA档 | 电流读数稳定在2~8mA范围(MSI 2.1MHz运行典型值),记录为IRUN |
| 2 | 断开电源,将MEASURE_MODE设为1,重新编译烧录 | 上电后先观察到运行电流约5秒,随后电流突降至µA级 |
| 3 | 将万用表切换至µA档,等待读数稳定 | 电流读数应小于3.4µA(STM32L071 Standby模式典型值,25°C),记录为ISTBY |
| 4 | 将PA0引脚短接到GND(下降沿唤醒) | 电流回升至mA级,程序重新从main开始执行,证明唤醒功能正常 |
通过标准:IRUN在2~8mA区间,ISTBY≤3.4µA,且PA0接地后系统能复位重启。若ISTBY明显偏高(如>10µA),检查是否有外部器件漏电、GPIO浮空输入或调试器仍连接。
注意事项
- 测量待机电流时,必须断开调试器(ST-LINK)连接,因为调试接口本身会消耗数百µA电流。
- 万用表使用前需短接表笔校准,确保在µA档位下读数准确。
- 若使用开发板而非自制最小系统,需确认板载LDO静态电流是否已隔离。