1. 测量MCU基础功耗

测量MCU基础功耗 学习卡片

任务定义

本案例面向STM32L0系列MCU(以STM32L071为例),完成基础功耗测量。目标是在最小系统配置下,分别测量MCU在运行模式(Run)与待机模式(Standby)下的电流消耗,并验证待机模式唤醒功能正常。测量结果用于建立该芯片的功耗基线,为后续低功耗优化提供对比依据。

硬件连接与测量拓扑

使用精密万用表(如Keysight 34461A)串联在MCU供电回路中测量电流。测量点位于3.3V电源输出与STM32L0开发板VDD引脚之间。板载LED、调试器供电等额外负载必须断开或跳线隔离,确保万用表读数仅为MCU及其必要外围电路(去耦电容、复位上拉电阻)的电流。

3.3V电源 DC Supply 万用表 电流档 (mA/µA) 串联接入 STM32L071 最小系统板 VDD / GND PA0=唤醒引脚 GND 回路 IHOT VDD

代码实现

固件逻辑:系统上电后运行在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静态电流是否已隔离。