STM32 待机模式与唤醒实验(标准库函数版)

STM32 待机模式与唤醒实验(标准库函数版)

一、核心原理与硬件基础

1. 待机模式(Standby Mode)简介

待机模式是STM32的最低功耗模式,核心特性:

2. 关键寄存器与库函数

模块 寄存器/函数 功能
电源控制(PWR) PWR_EnterSTANDBYMode() 进入待机模式(标准库函数)
  PWR_GetFlagStatus(PWR_FLAG_SB) 检查是否由待机模式唤醒(复位标志)
  PWR_ClearFlag(PWR_FLAG_SB) 清除待机唤醒标志
复位控制(RCC) RCC_GetFlagStatus(RCC_FLAG_PORRST) 检查复位源(上电/待机唤醒/看门狗等)

3. 唤醒源配置(以WKUP引脚为例)

二、硬件设计方案

1. 核心硬件需求

2. 电路连接要点

三、软件设计与核心代码(标准库版)

1. 系统架构

2. 核心代码实现

2.1 头文件与宏定义(standby_wakeup.h

#ifndef __STANDBY_WAKEUP_H
#define __STANDBY_WAKEUP_H

#include "stm32f10x.h"

// 引脚定义
#define WKUP_PIN     GPIO_Pin_0
#define WKUP_PORT    GPIOA
#define LED_PIN      GPIO_Pin_0
#define LED_PORT     GPIOB

// 函数声明
void System_Init(void);          // 系统初始化(时钟、GPIO、PWR)
void Enter_Standby_Mode(void);   // 进入待机模式
void Wakeup_Handler(void);       // 唤醒后处理(复位时调用)

#endif /* __STANDBY_WAKEUP_H */

2.2 源文件实现(standby_wakeup.c

#include "standby_wakeup.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"

/**
 * @brief  系统初始化(时钟、GPIO、PWR)
 * @param  无
 * @retval 无
 */
void System_Init(void) {
    // 1. 配置系统时钟(72MHz,F103C8T6)
    RCC_DeInit();                     // 复位RCC
    RCC_HSEConfig(RCC_HSE_ON);        // 使能外部高速时钟(8MHz)
    while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);  // 等待HSE就绪
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  // PLL=8MHz×9=72MHz
    RCC_PLLCmd(ENABLE);               // 使能PLL
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);  // 等待PLL就绪
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  // 系统时钟=PLL
    RCC_HCLKConfig(RCC_SYSCLK_Div1);   // HCLK=72MHz
    RCC_PCLK1Config(RCC_HCLK_Div2);    // PCLK1=36MHz
    RCC_PCLK2Config(RCC_HCLK_Div1);    // PCLK2=72MHz
    
    // 2. 配置GPIO(WKUP引脚:PA0输入,LED:PB0推挽输出)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    // WKUP引脚(PA0):输入模式(上拉,默认高电平,按下接地)
    GPIO_InitStruct.GPIO_Pin = WKUP_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  // 上拉输入
    GPIO_Init(WKUP_PORT, &GPIO_InitStruct);
    
    // LED引脚(PB0):推挽输出
    GPIO_InitStruct.GPIO_Pin = LED_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(LED_PORT, &GPIO_InitStruct);
    GPIO_ResetBits(LED_PORT, LED_PIN);  // 初始熄灭
    
    // 3. 配置PWR(使能WKUP唤醒功能)
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);  // 使能PWR时钟
    PWR_WakeUpPinCmd(ENABLE);  // 使能WKUP引脚唤醒(PA0)
}

/**
 * @brief  进入待机模式
 * @param  无
 * @retval 无
 */
void Enter_Standby_Mode(void) {
    // 1. 关闭外设时钟(降低功耗)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, DISABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, DISABLE);  // 仅保留PWR时钟
    
    // 2. 清除唤醒标志(避免误触发)
    PWR_ClearFlag(PWR_FLAG_WU);    // 清除唤醒标志
    PWR_ClearFlag(PWR_FLAG_SB);    // 清除待机标志
    
    // 3. 进入待机模式(标准库函数)
    PWR_EnterSTANDBYMode();  // 执行后系统进入待机,仅WKUP引脚可唤醒
}

/**
 * @brief  唤醒后处理(系统复位时调用)
 * @param  无
 * @retval 无
 */
void Wakeup_Handler(void) {
    // 检查是否由待机模式唤醒(PWR_FLAG_SB标志置位)
    if (PWR_GetFlagStatus(PWR_FLAG_SB) != RESET) {
        PWR_ClearFlag(PWR_FLAG_SB);  // 清除待机标志
        GPIO_SetBits(LED_PORT, LED_PIN);  // 点亮LED提示唤醒成功
        // 可添加其他唤醒后操作(如串口打印、状态恢复)
    }
}

2.3 主程序调用示例(main.c

#include "stm32f10x.h"
#include "standby_wakeup.h"
#include "delay.h"  // 简单延时函数(需自行实现)

int main(void) {
    System_Init();       // 系统初始化
    Wakeup_Handler();    // 唤醒后处理(首次上电不执行,唤醒后执行)
    
    // 主循环:检测普通按键(PC13)触发进入待机
    while (1) {
        if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13) == Bit_RESET) {  // 按键按下(低电平)
            Delay_ms(20);  // 消抖
            if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13) == Bit_RESET) {
                Enter_Standby_Mode();  // 进入待机模式
            }
        }
        // 其他低功耗任务(如传感器采集,此处省略)
    }
}

四、关键注意事项

1. 待机模式进入步骤

  1. 关闭外设时钟:除PWR外,关闭其他外设时钟(如GPIO、UART),减少漏电流。
  2. 清除唤醒标志:通过PWR_ClearFlag()清除PWR_FLAG_WUPWR_FLAG_SB,避免历史标志干扰。
  3. 使能唤醒源:通过PWR_WakeUpPinCmd(ENABLE)使能WKUP引脚,或配置RTC闹钟。
  4. 调用PWR_EnterSTANDBYMode():执行后系统立即进入待机,程序停止运行。

2. 唤醒后处理

3. 常见问题排查

问题 原因 解决方案
无法进入待机模式 未使能PWR时钟或未调用PWR_EnterSTANDBYMode 检查RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE)是否执行
唤醒后无反应 未清除PWR_FLAG_SB或未检测标志 main()开头调用Wakeup_Handler(),检查标志
待机电流过大 外设未完全关闭(如ADC、DMA时钟) 关闭所有非必要外设时钟,确保仅PWR工作

参考代码 STM32 待机并唤醒实验(库函数) www.youwenfan.com/contentcnt/133694.html

五、系统调试与优化

1. 调试步骤

阶段 操作 工具
硬件检查 测量PA0电压(按下按键时应为3.3V,释放时0V) 万用表、示波器
待机电流测试 进入待机后,测量VCC电流(应<2μA) 万用表(电流档,串联测量)
唤醒测试 按下WKUP按键,观察LED是否点亮(唤醒成功) 肉眼观察、逻辑分析仪(复位信号)

2. 低功耗优化

六、扩展应用

七、总结

本实验通过标准库函数实现了STM32的待机模式与WKUP引脚唤醒,核心步骤包括PWR配置外设关闭进入待机唤醒后复位处理。待机模式适用于电池供电场景,可将系统功耗降至μA级,配合定时唤醒或外部触发,实现“休眠-工作”循环。

专注于matlab/simulink,电子电路,编程