当前位置: 首页 > news >正文

【STM32单片机】#14 PWR电源控制

主要参考学习资料:

B站@江协科技

STM32入门教程-2023版 细致讲解 中文字幕

开发资料下载链接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwd=dspb

单片机套装:STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协

目录

  • PWR简介
    • 电源框图
    • 电压监测(了解)
      • 上电复位和掉电复位
      • 可编程电压监测器
    • 低功耗模式
      • 模式选择
      • 睡眠模式
      • 停机模式
      • 待机模式
  • 函数详解
    • PWR_DeInit函数
    • PWR_PVDCmd函数
    • PWR_PVDLevelConfig函数
    • PWR_WakeUpPinCmd函数
    • PWR_EnterSTOPMode函数
    • PWR_EnterSTANDBYMode函数
    • 标志位函数
  • 实验30 修改主频
    • 接线图
    • system_stm32f10x文件
    • 主程序
  • 实验31 睡眠模式+串口发送+接收
    • 接线图
    • 主程序
  • 实验32 停机模式+对射式红外传感器计次
    • 接线图
    • 主程序
  • 实验33 待机模式+实时时钟
    • 接线图
    • 主程序

PWR简介

  • PWR(Power Control)电源控制
  • PWR负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能。
  • 可编程电压监测器(PVD)可以监控VDD电源电压,当VDD下降到PVD阈值以下或上升到PVD阈值之上时,PVD会触发中断,用于执行紧急关闭任务(非本节重点)。
  • 低功耗模式包括睡眠模式(Sleep)、停机模式(Stop)和待机模式(Standby),可在系统空闲时降低STM32的功耗,延长设备使用时间。
  • 主频和电流消耗大致呈正比,降低主频也能显著降低功耗。

电源框图

上图为STM32供电方案,可分为模拟部分供电(VDDA)、数字部分供电(VDD+1.8V)和后备供电。各供电区域负责的设备已列出。

VDDA供电区域主要负责模拟部分的供电,供电正极为VDDA,负极为VSSA。其中AD转换器还有参考电压供电引脚VREF+和VREF-,在引脚多的芯片型号会单独引出,而在F103C8T6中已经在内部分别接到了VDDA和VSSA。

中间部分分为VDD供电区域和1.8V供电区域,VDD经电压调节器降压到1.8V提供给1.8V供电区域。后备供电区域中,低电压检测器控制开关,在VDD有电时由VDD供电,VDD没电时由VBAT供电。

电压监测(了解)

上电复位和掉电复位

当VDD或VDDA电压过低时,STM32内部电路直接产生复位。电压小于下限PDR时复位,大于上限POR时解除复位,中间有40mV的迟滞电压防抖,复位信号Reset低电平有效。POR、PDR和复位滞后时间均可在芯片数据手册查询。

可编程电压监测器

可编程电压监测器的工作流程与上电/掉电复位类似,但阈值电压可以手动调节,调节范围可在芯片数据手册查询,一般高于上电/掉电复位电压。PVD输出在电压过低时为1,电压正常时为0,可在上升/下降沿申请外部中断提醒程序进行适当处理。

低功耗模式

上表对三种低功耗模式进行了详细的对比。其中第二列为进入对应模式所需的配置,第三列为进入对应模式后的唤醒方法,后三列为进入对应模式后关闭的电路(电压调节器相当于1.8V供电区域的电源)。三种模式从上到下,关闭的电路越来越多,也越来越省电,越来越难唤醒。对于具体的省电效果,正常模式和睡眠模式电流消耗(数量级)均在10mA,停机模式为10 μ \mu μA,待机模式为1 μ \mu μA。

模式选择

执行WFI(Wait For Interrupt)或WFE(Wait For Event)指令后,STM32进入低功耗模式。在触发低功耗模式之前,配置寄存器进行模式选择的方式如下图所示,其中寄存器的每个位已由库函数封装好,无需自行配置。

睡眠模式

  • 执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行。
  • SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠。
  • 在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态。
  • WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒。
  • WFE指令进入睡眠模式,可被唤醒事件唤醒。

停机模式

  • 执行完WFI/WFE指令后,STM32进入停机模式,程序暂停运行,唤醒后程序从暂停的地方继续运行。
  • 1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下来。
  • 在停机模式下,所有的I/O引脚都保持它们在运行模式时的状态。
  • 当一个中断或唤醒事件导致退出停机模式时,HSI被选为系统时钟,因此唤醒后需重新启动HSE配置主频为72MHz。
  • 当电压调节器处于低功耗模式下,系统从停机模式退出时,会有一段额外的启动延时。
  • WFI指令进入停机模式,可被任意一个EXTI中断唤醒。
  • WFE指令进入停机模式,可被任意一个EXTI事件唤醒。

待机模式

  • 执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行。
  • 整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电。
  • 在待机模式下,所有的I/O引脚变为高阻态(浮空输入)。
  • WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式。

函数详解

PWR_DeInit函数

简介:恢复缺省配置。

参数:void

PWR_PVDCmd函数

简介:使能可编程电压监测器。

参数:使能/失能

PWR_PVDLevelConfig函数

简介:配置PVD阈值。

参数:阈值

PWR_PVDLevel_2V2/.../9(2.2~2.9V)

PWR_WakeUpPinCmd函数

简介:使能WKUP引脚(PA0),配合待机模式的WKUP上升沿唤醒。

参数:使能/失能

PWR_EnterSTOPMode函数

简介:进入停机模式。

参数一:电压调节器状态

PWR_Regulator_ON(开启)
PWR_Regulator_LowPower(低功耗)

参数二:唤醒方式

PWR_STOPEntry_WFI/WFE(中断/事件)

PWR_EnterSTANDBYMode函数

简介:进入待机模式。

参数:void

标志位函数

PWR_GetFlagStatus函数

PWR_ClearFlag函数

参数:PWR标志位

PWR_FLAG_WU/SB/PWDO(唤醒/待机/电压监测器输出)

实验30 修改主频

接线图

system_stm32f10x文件

system文件提供了两个外部可调用的函数和一个外部可调用的变量:

  • SystemInit函数:配置时钟树,复位后在启动文件中自动调用。
  • SystemCoreClock变量:主频频率。
  • SystemCoreClockUpdate函数:更新主频频率。

源文件system_stm32f10x.c中如下部分可更改主频的宏定义,解除对应的注释即可选择想要的系统主频。其中else之前的部分为VL超值系列可选主频。当前主频为72MHz。

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */#define SYSCLK_FREQ_24MHz  24000000
#else
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz  24000000 */ 
/* #define SYSCLK_FREQ_36MHz  36000000 */
/* #define SYSCLK_FREQ_48MHz  48000000 */
/* #define SYSCLK_FREQ_56MHz  56000000 */
#define SYSCLK_FREQ_72MHz  72000000
#endif

若文件为只读状态,可以在文件资源管理器中右键对应文件更改属性,取消勾选只读。

SystemInit()首先启动HSI并恢复缺省配置,随后调用SetSysClock()函数会根据不同的宏定义执行相应的SetSysClockToxx()函数完成相应的时钟配置。

主程序

以下代码显示主频,并以72MHz下的1s为周期闪烁Running字符串。

#include "stm32f10x.h" 
#include "Delay.h"
#include "OLED.h"int main(void)
{OLED_Init();OLED_ShowString(1, 1, "SYSCLK:");OLED_ShowNum(1, 8, SystemCoreClock, 8);while(1){OLED_ShowString(2, 1, "Running");Delay_ms(500);OLED_ShowString(2, 1, "       ");Delay_ms(500);}
}

此时Running以现实的1s为周期闪烁。

现通过宏定义修改主频为36MHz:

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */#define SYSCLK_FREQ_24MHz  24000000
#else
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz  24000000 */ 
#define SYSCLK_FREQ_36MHz  36000000
/* #define SYSCLK_FREQ_48MHz  48000000 */
/* #define SYSCLK_FREQ_56MHz  56000000 */
/* #define SYSCLK_FREQ_72MHz  72000000 */
#endif

此时Running闪烁周期延长一倍。

由于修改主频会要求很多涉及精准计时的计算做好匹配工作,一般不建议采用。

实验31 睡眠模式+串口发送+接收

接线图

主程序

在实验21 串口发送+接收的基础上修改。

#include "stm32f10x.h" 
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"uint8_t RxData;int main(void)
{OLED_Init();Serial_Init();OLED_ShowString(1, 1, "RxDara:");while(1){if (Serial_GetRxFlag()){RxData = Serial_GetRxData();Serial_SendByte(RxData);OLED_ShowHexNum(1, 8, RxData, 2);}//监测低功耗状态OLED_ShowString(2, 1, "Running");Delay_ms(100);OLED_ShowString(2, 1, "       ");Delay_ms(100);//默认配置开启睡眠模式__WFI();}
}

此时只有当我们向串口发送数据时,Running才会闪烁一次,并回传一次数据。

程序运行时,第一次循环即进入睡眠状态,程序停止在WFI指令,CPU睡眠,但各个外设例如USART仍处于工作状态。USART外设在收到数据时产生中断唤醒CPU,程序在暂停的地方继续运行,先进入中断服务函数,再回到主循环执行一轮循环进入下一次睡眠,如此循环往复。

实验32 停机模式+对射式红外传感器计次

接线图

主程序

在实验6 对射式红外传感器计次的基础上修改。

原驱动程序中博主采用了延时100ms消抖,经实测中断处理时间过长会导致唤醒失败,因此将中断服务函数修改如下:

//中断函数名称在启动文件startup_stm32f10x_md.s中规定
void EXTI15_10_IRQHandler(void)
{//检查中断挂起标志位if(EXTI_GetITStatus(EXTI_Line14) == SET){//再次判断引脚电平if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0){CountSensor_Count ++;}EXTI_ClearITPendingBit(EXTI_Line14);}
}

主程序修改如下:

#include "stm32f10x.h" 
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"int main(void)
{OLED_Init();CountSensor_Init();//开启PWR时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);OLED_ShowString(1, 1, "Count:");while(1){OLED_ShowNum(1, 7, CountSensor_Get(), 5);//监测低功耗状态OLED_ShowString(2, 1, "Running");Delay_ms(100);OLED_ShowString(2, 1, "       ");Delay_ms(100);//进入停机模式(电压调节器开启,中断唤醒)PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);}
}

此时每遮挡一次对射式红外传感器,计数加一,Running闪烁一次。有时闪烁两次是因为信号抖动导致遮挡和移开均产生中断信号。

除此之外,复位后Running第一次闪烁时间短暂,后续遮挡Running闪烁变慢,这是由于前文介绍的停机模式唤醒后HSI被选为系统时钟,只需在进入停机模式之后加上 SystemInit(); \texttt{SystemInit();} SystemInit();重新配置时钟为HSE即可。

实验33 待机模式+实时时钟

接线图

主程序

在实验29 实时时钟的基础上修改。

#include "stm32f10x.h" 
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"int main(void)
{OLED_Init();MyRTC_Init();//开启PWR时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//更改显示布局//计数值OLED_ShowString(1, 1, "CNT :");//闹钟值OLED_ShowString(2, 1, "ALR :");//闹钟标志位OLED_ShowString(3, 1, "ALRF:");//设置闹钟值为复位10秒后//闹钟寄存器只写不读,先定义变量存储闹钟值uint32_t Alarm = RTC_GetCounter() + 10;RTC_SetAlarm(Alarm);OLED_ShowNum(2, 6, Alarm, 10);while(1){OLED_ShowNum(1, 6, RTC_GetCounter(), 10);//显示闹钟标志位OLED_ShowNum(3, 6, RTC_GetFlagStatus(RTC_FLAG_ALR), 1);//监测低功耗状态OLED_ShowString(4, 1, "Running");Delay_ms(100);OLED_ShowString(4, 1, "       ");Delay_ms(100);//待机前关闭所有外部耗电电路以达到省电目的OLED_Clear();PWR_EnterSTANDBYMode();}
}

待机模式唤醒后程序从头开始运行,因此该程序现象为复位后OLED闪烁一次,十秒之后触发闹钟事件再次闪烁,往后每隔十秒闪烁一次。

在while循环之前加上 PWR_WakeUpPinCmd(ENABLE); \texttt{PWR\_WakeUpPinCmd(ENABLE);} PWR_WakeUpPinCmd(ENABLE);可实现WKUP引脚(PA0)唤醒,此时每次将该引脚用跳线接到高电平即可观察到OLED闪烁。

相关文章:

  • 神经网络之互动练习详解:从基础到拟合非线性数据
  • C++ 内存泄漏相关
  • OpenShift AI - OpenShift 支持的 NVIDIA GPU 共享和分区技术 2
  • Netty 的 Reactor 模型
  • 我用cursor 搭建了临时邮箱服务-Temp Mail 365
  • K-means
  • 机器学习-简要与数据集加载
  • React Native【详解】搭建开发环境,创建项目,启动项目
  • 虚拟机连不上网只有lo地址
  • 高频PCB设计如何选择PCB层数?
  • 2025年LangChain(V0.3)开发与综合案例
  • Spring MVC 如何自动将请求参数映射到 Controller 方法的参数对象(POJO)上?
  • 把其他conda的env复制到自己电脑的conda上
  • 【ULMD】基于单峰标签生成和模态分解的多模态情感分析
  • Java大师成长计划之第13天:Java中的响应式编程
  • Python实现NOA星雀优化算法优化BP神经网络分类模型项目实战
  • P56-P60 统一委托,关联游戏UI,UI动画,延迟血条
  • CSS Border 三角形阴影与多重边框的制作
  • ROS2:自定义接口文件(无废话)
  • 第100+40步 ChatGPT学习:R语言实现多轮建模
  • 前瞻|美联储明晨“按兵不动”几无悬念:关税战阴霾下,会否释放降息信号
  • 白俄罗斯政府代表团将访问朝鲜
  • 1101名优秀运动员拟保送,全红婵、黄雨婷、盛李豪在列
  • “五一”假期全社会跨区域人员流动量超14.65亿人次
  • 五一假期上海虹桥边检站出入境近4.7万人次,韩国入境旅客同比增118%
  • 听炮检书:柳诒徵1927年的选择