STM32电源控制详解
STM32 的 PWR(Power Control)外设 是用于管理微控制器电源模式和外设电源控制的模块。通过 PWR 外设,可以实现低功耗模式、电压调节、备份域控制等功能,从而优化系统的功耗和性能。
stm32内部电源框图
电源区域
-
VDD 供电区(主电源):
- 主要用于为 CPU 核心、内存 和 数字外设 提供电力。
- VDD 通常是 3.3V,为单片机的所有数字部分提供电源。
- 该区域还包括 电压调节器,用于确保提供稳定的电源给各个模块。
-
VSSA 和 VDDA(模拟部分电源):
- VSSA 是 模拟地,用于提供模拟部分的参考电压。
- VDDA 用于为模拟模块供电,如 A/D 转换器、温度传感器 等。
- 该部分通常由 外部稳压电源 提供 2.4V 至 3.6V 的电源。
-
1.8V 供电区:
- 该部分为一些低功耗模块提供 1.8V 电压,主要用于 CPU 核心、低功耗寄存器 和一些特定的外设。
- 在大多数现代微控制器中,1.8V 电源用于 低功耗操作,减少能耗。
-
低电压检测电路:
- 用于监控电源电压是否过低。当电压低于一定值时,系统可能会执行复位或其他保护机制,防止因电压不稳定导致的异常操作。
时钟部分
-
PLL(锁相环):
- 用于提供更高频率的时钟,支持更快的处理速度。
- 通常,STM32 系列单片机使用 PLL 来从较低频率的输入时钟生成更高的主时钟频率(例如从 8 MHz 外部晶振生成 72 MHz)。
-
LSE(低速外部晶体振荡器):
- 提供给 RTC(实时时钟) 等低速外设一个稳定的时钟源,通常为 32.768 kHz。
- 这个时钟源用于处理低功耗操作,如 待机模式 和 定时器操作。
备用电源
-
V_BAT(备用电池):
- 用于为 RTC 和 其他低功耗外设 提供电力,确保这些模块在主电源关闭时依然能够工作。
- 这通常是由 CR2032 电池 或类似电池提供的。
-
RCC BDCR 寄存器:
- 这个寄存器管理 时钟源,包括 LSE 和 RTC 等外设的时钟。
CPU 和存储器
I/O 电路
PWR 外设的主要功能
1. 电源模式管理:
– 支持多种低功耗模式,如眠模式、停止模式和待机模式。
– 通过配置 PWR 寄存器,可以进入或退出这些模式。
2. 电压调节:
– 支持动态电压调节(DVS),通过调整核心电压来优化功耗和性能。
PWR 上电复位与掉电复位
PWR(Power)模块在 STM32 系列微控制器中主要用于管理电源相关的操作,例如上电、掉电复位、低功耗模式等。电源模块控制着系统的电源源供给,涉及到 上电复位 和 掉电复位 两种状态。
1. 上电复位 (Power-On Reset, POR)
上电复位是指单片机在接通电源时,系统自动进行复位的过程。上电时复位的作用是确保芯片的状态从不确定的状态恢复到已知的初始状态。上电复位通常由内部的复位电路完成,不需要外部触发。其主要作用包括:
在 STM32 系列中,PWR模块中的 POR 机制通常由电源电压(VDD)稳定后触发复位信号。
2. 掉电复位 (Brownout Reset, BOR)
掉电复位用于监控电源电压的稳定性。如果电源电压跌至一个设定的阈值以下,系统将自动复位,以避免在电压不稳定时继续工作。BOR 保护功能可以防止系统在低电压下继续运行,避免导致数据错误或系统异常。掉电复位的特性:
STM32 提供了一个 BOR 电压检测器,可以设置为不同的阈值,用户可以根据需要启用或禁用该功能。
总结
PWR 可编程电压电测器 (PVD)
PVD(Programmable Voltage Detector,可编程电压电测器)是 STM32 微控制器中的一个重要功能,它用于监测芯片的电源电压,并在电压超出设定范围时触发中断或复位。PVD 主要用于在电压过低时保护系统,避免因电压不稳定而导致的数据丢失或系统不稳定。
PVD 的功能和作用
PVD 主要有以下功能:
-
电压监测:
- PVD 可监测供电电压是否超出预定范围,确保设备在稳定的电压范围内运行。
- 监测电源电压下降到指定阈值时,进行保护操作。
-
可编程阈值:
- PVD 允许用户设置电压阈值(例如 2.7V、2.8V 等),并在电压低于该阈值时触发相关操作。
-
保护系统:
- 如果电源电压降到低于预设阈值,PVD 会触发复位或者中断,以保护系统不在不可靠的电压下继续工作,避免潜在的数据损坏或异常行为。
-
启用和禁用功能:
- 用户可以根据需要启用或禁用 PVD 功能。
- 通过配置寄存器,可以设定触发电压的阈值,并选择中断方式。
PVD(可编程电压电测器)工作原理详细解释:
PVD 是 STM32 系列芯片中的一个重要电源管理功能,主要用于监测系统的电源电压,确保系统在稳定的电压下运行。具体来说,PVD 的工作原理如下:
1. 电压监测
2. 触发事件(复位或中断)
当电源电压下降到设定的阈值以下时,PVD 会触发以下两种可能的事件之一:
3. 低功耗模式控制
在电压下降时,PVD 还可以配合 低功耗模式 使用,帮助系统尽量减少功耗。具体操作包括:
4. 系统复位后恢复稳定
PVD 可以确保在电压过低时系统能快速恢复到安全状态。具体来说:
5. 与其他电源管理功能的配合
PVD 通常与 STM32 的其他电源管理功能结合使用:
工作流程
- PVD 阈值设定:首先,用户通过编程设置电压阈值,例如 2.7V。
- 实时监控:PVD 会不断监测系统电源电压。
- 电压低于阈值:当电压低于 2.7V 时,PVD 会触发预设的操作(复位或中断)。
- 触发操作:
- 如果选择了复位,芯片将重新启动,恢复到安全状态。
- 如果选择了中断,系统会执行中断服务程序,通常会进行电压恢复处理、进入低功耗模式或关闭非必要外设。
- 电压恢复正常:当电源电压恢复到正常值时,PVD 监控停止,系统继续正常运行
PVD 的配置:
在 STM32 微控制器中,PVD 的配置通常是通过编程寄存器来完成的。以下是 PVD 配置的几个常用步骤:
- 选择阈值电压:可以通过 PVDCR 寄存器配置阈值电压(如 2.4V、2.7V 等)
- 启用 PVD:通过设置相应的控制寄存器,启用 PVD 功能。
- 配置中断(可选):如果需要,可以设置 PVD 中断,使得系统在触发 PVD 时可以进行相关处理。
PVD 配置示例:
// 启用 PVD 功能并设置阈值为 2.7V
PWR_PVDLevelConfig(PWR_PVDLevel_2); // 设置 PVD 阈值为 2.7V
PWR_PVDCmd(ENABLE); // 启用 PVD
总结
PVD(可编程电压电测器)是一个非常重要的功能,它能够监测电源电压并保护系统在电压异常时采取相应措施。通过设置阈值,可以在电压降到设定值以下时触发中断或复位,从而避免电压不稳定导致的系统错误或数据丢失。
低功耗模式:
STM32 的低功耗模式概述
在 STM32 微控制器中,低功耗模式主要有以下几种:
- 睡眠模式(Sleep Mode)
- 停机模式(Stop Mode)
- 待机模式(Standby Mode)
1. 睡眠模式(Sleep Mode)
睡眠模式是 STM32 的最轻功耗模式,主要用于系统处于空闲状态时,但仍然需要保持快速响应。
工作原理:
功耗:
唤醒方式:
SLEEP-NOW
或 SLEEP-ON-EXIT
进入。SLEEP-NOW
表示立即进入睡眠模式,SLEEP-ON-EXIT
则是在当前指令执行完后进入睡眠模式。2. 停机模式(Stop Mode)
停机模式是一种较低功耗的模式,适用于需要尽可能节省电池能量的场景。
工作原理:
功耗:
唤醒方式:
PDDS
和 SLEEPDEEP
位进入。在此模式下,CPU 核心停止工作,整个系统停止所有活动,进入低功耗状态。WKUP
引脚触发时可以唤醒。3. 待机模式(Standby Mode)
待机模式是 STM32 微控制器的 最低功耗模式,适用于设备长时间处于休眠状态,但需要保证某些功能(如 RTC、备份寄存器)持续工作。
工作原理:
功耗:
唤醒方式:
PDDS
和 SLEEPDEEP
位进入,结合 WKUP
引脚触发。WKUP
引脚或者 NRST
引脚触发时可以恢复。PWR 低功耗模式的选择和配置
在 STM32 中,可以通过 PWR 控制寄存器来配置和启用不同的低功耗模式。具体的选择取决于系统的需求:需要较低的功耗还是较短的响应时间。
配置步骤:
- 选择低功耗模式:根据应用需求选择睡眠模式、停机模式或待机模式。
- 配置外设:配置是否启用需要保留工作的外设(如 RTC、外部中断等)。
- 使能相应的模式:通过 PWR_CR 寄存器配置并使能所选的低功耗模式。
- 唤醒配置:配置唤醒条件,例如定时器中断、外部中断等。
示例代码(进入睡眠模式):
// 配置 STM32 进入睡眠模式
void Enter_Sleep_Mode(void)
{
// 禁用不必要的外设时钟,降低功耗
// 使能睡眠模式
PWR_EnterSleepMode(PWR_SLEEPEntry_WFI);
}
示例代码(进入停机模式):
// 配置 STM32 进入停机模式
void Enter_Stop_Mode(void)
{
// 禁用不必要的外设时钟,进入停机模式
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}
示例代码(进入待机模式):
// 配置 STM32 进入待机模式
void Enter_Standby_Mode(void)
{
// 进入待机模式
PWR_EnterSTANDBYMode();
}
总结
3. 备份域控制:
– 管理备份域(Backup Domain)的电源,包括备份寄存器(Backup Registers)和 RTC(实时时钟)。
– 在 V<sub>BAT</sub> 模式下,备份域可以由电池供电。
4. 唤醒机制:
– 提供多种唤醒源(如外部中断、RTC 闹钟等),用于从低功耗模式唤醒。
5. 电源电压监测:
– 提供电源电压监测功能(PVD,Programmable Voltage Detector),用于检测电源电压是否低于设定阈值。
PWR 外设的主要寄存器
1. PWR_CR(Power Control Register):
– 用于配置低功耗模式、电压调节和电源电压监测。
2. PWR_CSR(Power Control/Status Register):
– 用于查看电源状态(如是否处于低功耗模式)和清除唤醒标志。
3. PWR_CR2(Power Control Register 2):
– 用于配置动态电压调节和备份域控制。
4. PWR_CR3(Power Control Register 3):
– 用于配置唤醒引脚和低功耗模式下的外设行为。
5. PWR_CR4(Power Control Register 4):
1修改主频: 通过在system_stm32f10x.c文件中修改主频参数来调整时间
OLED_Init();
OLED_ShowString (1,1,"sysytemclock:");
OLED_ShowNum (2,1,SystemCoreClock ,8);
while(1)
{
OLED_ShowString (3,1,"ruing");
delay_ms (500);
OLED_ShowString (3,1," ");
delay_ms (500);
}
#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
2睡眠模式下的利用串口收发数据并唤醒睡眠模式:
1初始化USART
2开启接受中断使能
3在主函数whie(1)循环里面接受上位机发送回来的数据
4在OLDE上显示数据,循环显示"runing"
4进入睡眠模式后再显示数据,循环显示"runing"
uint32_t srambuff[SIZEOF];
uint16_t num;
float distance;
int main(void){
uint8_t Data;
Usart_Init();
OLED_Init();
OLED_ShowString (1,1,"RXData:");
while(1)
{
uint16_t Datat;
if(Check_myflag()==1){
Data=USART_Return();
serval_sendbyte( Data);
OLED_ShowNum (1,8, Data,2);
}
OLED_ShowString (2,1,"ruing");
delay_ms(100);
OLED_ShowString (2,1," ");
delay_ms(100);
__WFI ();
}
}
#define __enable_fault_irq __enable_fiq
#define __disable_fault_irq __disable_fiq
#define __NOP __nop
#define __WFI __wfi
#define __WFE __wfe
#define __SEV __sev
#define __ISB() __isb(0)
#define __DSB() __dsb(0)
#define __DMB() __dmb(0)
#define __REV __rev
#define __RBIT __rbit
#define __LDREXB(ptr) ((unsigned char ) __ldrex(ptr))
#define __LDREXH(ptr) ((unsigned short) __ldrex(ptr))
#define __LDREXW(ptr) ((unsigned int ) __ldrex(ptr))
#define __STREXB(value, ptr) __strex(value, ptr)
#define __STREXH(value, ptr) __strex(value, ptr)
#define __STREXW(value, ptr) __strex(value, ptr)
uint16_t GEtDatat;
uint16_t myflag;
void Usart_Init()
{
//配置GPIO和USART的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
//配置关于USART的TX的GPIO结构体
GPIO_InitTypeDef usartgpio_Initsturt;
usartgpio_Initsturt.GPIO_Mode =GPIO_Mode_AF_PP ;
usartgpio_Initsturt .GPIO_Pin =GPIO_Pin_9 ;
usartgpio_Initsturt .GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&usartgpio_Initsturt);
//配置关于USART的RX的GPIO结构体
usartgpio_Initsturt .GPIO_Mode = GPIO_Mode_IN_FLOATING;
usartgpio_Initsturt .GPIO_Pin = GPIO_Pin_10 ;
GPIO_Init(GPIOA,&usartgpio_Initsturt);
//配置usart的结构体
USART_InitTypeDef usart_Initsturt;
usart_Initsturt .USART_BaudRate =9600;
usart_Initsturt .USART_HardwareFlowControl =USART_HardwareFlowControl_None;
usart_Initsturt .USART_Mode = USART_Mode_Rx |USART_Mode_Tx ;
usart_Initsturt .USART_Parity = USART_Parity_No ;
usart_Initsturt .USART_StopBits =USART_StopBits_1;
usart_Initsturt .USART_WordLength =USART_WordLength_8b ;
USART_Init(USART1, &usart_Initsturt);
//USART_ITConfig(USART1, USART_IT_RXNE,ENABLE );//NVIC中断输出使能
//NVIC_Configuration();//配置NVIC中断使能函数
USART_Cmd(USART1, ENABLE);//使能USART函数
USART_ITConfig(USART1,USART_IT_RXNE, ENABLE );
}
void NVIC_Configuration()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_INit;
NVIC_INit.NVIC_IRQChannel =USART1_IRQn ;
NVIC_INit .NVIC_IRQChannelCmd =ENABLE ;
NVIC_INit .NVIC_IRQChannelPreemptionPriority =1;
NVIC_INit .NVIC_IRQChannelSubPriority =1;
NVIC_Init( &NVIC_INit);//初始化NVIC
}
void serval_sendbyte(uint8_t Data)
{
USART_SendData( USART1,Data);
while(USART_GetITStatus(USART1,USART_IT_TXE)==RESET );
}uint16_t USART_Return(void )
{
return GEtDatat;
}
uint16_t Check_myflag()
{
if( myflag==1)
{
myflag=0;
return 1;
}
else{
return 0;
}
}
3低功耗停机模式下利用外部中断对对射式传感器进行数据采集并唤醒该模式:
1初始化外部中断以及对应引脚的GPIO
2编写中断服务函数,对对射式传感器进行数据采集,并返回采集的值
3初始化PWR时钟,配置PWR进入低功耗停机模式,
4在主函数里面进行数据采集显示在OLED屏上并唤醒低功耗模式观察现象
float distance;
int main(void){
uint8_t Data;
Usart_Init();
OLED_Init();
exti_sensior_Init();
RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR, ENABLE);
OLED_ShowString (1,1,"Count:");
while(1)
{
OLED_ShowNum (1,8, Count_Set(),2);
OLED_ShowString (2,1,"ruing");
delay_ms(100);
OLED_ShowString (2,1," ");
delay_ms(100);
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
}
}
4利用RTC唤醒PWR低功耗待机模式:
- 初始化 RTC:配置 RTC 时钟源,设置时间和日期,使能 RTC 闹钟功能。
- 配置 PWR:使能 PWR 和 BKP 外设时钟,设置 RTC 闹钟时间,进入待机模式。
- RTC 闹钟中断处理:当 RTC 闹钟触发时,唤醒系统。
-
#include "stm32f10x.h" // 函数声明 void RTC_Configuration(void); void NVIC_Configuration(void); void PWR_Configuration(void); // 主函数 int main(void) { // 配置NVIC NVIC_Configuration(); // 配置RTC RTC_Configuration(); // 配置PWR PWR_Configuration(); while (1) { // 进入待机模式 PWR_EnterSTANDBYMode(); } } // 配置RTC void RTC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); // 复位备份区域 BKP_DeInit(); // 使能LSE RCC_LSEConfig(RCC_LSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) { } // 选择RTC时钟源 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); // 等待RTC寄存器同步 RTC_WaitForSynchro(); // 等待最近一次对RTC寄存器的写操作完成 RTC_WaitForLastTask(); // 设置RTC预分频值 RTC_SetPrescaler(32767); RTC_WaitForLastTask(); // 配置RTC闹钟中断 NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 使能RTC闹钟中断 RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); // 设置RTC闹钟时间(这里设置为10秒后) RTC_SetAlarm(RTC_GetCounter() + 10); RTC_WaitForLastTask(); } // 配置NVIC void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; // 配置PVD中断 NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 配置RTC闹钟中断 NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } // 配置PWR void PWR_Configuration(void) { // 使能PWR和BKP外设时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); // 允许访问备份区域 PWR_BackupAccessCmd(ENABLE); } // RTC闹钟中断处理函数 void RTCAlarm_IRQHandler(void) { if (RTC_GetITStatus(RTC_IT_ALR) != RESET) { // 清除RTC闹钟中断标志 RTC_ClearITPendingBit(RTC_IT_ALR); RTC_WaitForLastTask(); // 清除PWR唤醒标志 PWR_ClearFlag(PWR_FLAG_WU); } }
RTC_Configuration
函数:- 使能 PWR 和 BKP 外设时钟,并允许访问备份区域。
- 复位备份区域,使能 LSE(低速外部时钟)作为 RTC 时钟源。
- 配置 RTC 预分频值,使 RTC 时钟频率为 1Hz。
- 配置 RTC 闹钟中断,设置闹钟时间为当前时间加上 10 秒。
NVIC_Configuration
函数:- 配置 PVD 和 RTC 闹钟中断的优先级,并使能这两个中断。
PWR_Configuration
函数:- 使能 PWR 和 BKP 外设时钟,允许访问备份区域。
RTCAlarm_IRQHandler
函数:- 处理 RTC 闹钟中断,清除中断标志和 PWR 唤醒标志。
main
函数:- 调用上述配置函数,然后进入待机模式,等待 RTC 闹钟中断唤醒。
作者:想要成为糕手。