概述
41.1 STM32 的电源管理简介
1.1电源监控器
1.1.1上电复位与掉电复位 (POR 与 PDR)
当检测到 VDD 的电压低于阈值 VPOR 及 VPDR 时,无需外部电路辅助,STM32 芯片会自动保持在复位状态,防止因电压不足强行工作而带来严重的后果。在刚开始电压低于 VPOR 时 (约 1.92V),STM32 保持在上电复位状态 (POR,Power On Reset),当 VDD 电压持续上升至大于 VPOR 时,芯片开始正常运行,而在芯片正常运行的时候,当检测到 VDD 电压下降至低于 VPDR 阈值 (约 1.88V),会进入掉电复位状态 (PDR,Power Down Reset)。
1.1.2 可编程电压检测器 PVD
POR、PDR 功能是使用其电压阈值与外部供电电压 VDD 比较,当低于工作阈值时,会直接进入复位状态,这可防止电压不足导致的误操作。PVD 可配置 8 个等级。
1.2 STM32 的电源系统
STM32 把它的外设、内核等模块跟据功能划分了供电区域
STM32 的电源系统主要分为备份域电路、内核电路以及 ADC 电路三部分
(1) ADC 电源及参考电压(VDDA 供电区域)
为了提高转换精度,STM32 的 ADC 配有独立的电源接口,方便进行单独的滤波。ADC的工作电源使用 VDDA 引脚输入,使用 VSSA 作为独立的地连接,VREF 引脚则为 ADC提供测量使用的参考电压。
(2) 调压器供电电路(VDD/1.8V 供电区域)
在 STM32 的电源系统中调压器供电的电路是最主要的部分,调压器为备份域及待机电路以外的所有数字电路供电,其中包括内核、数字外设以及 RAM,调压器的输出电压约为 1.8V,因而使用调压器供电的这些电路区域被称为 1.8V 域。调压器可以运行在“运行模式”、“停止模式”以及“待机模式”。在运行模式下,1.8V域全功率运行;在停止模式下 1.8V 域运行在低功耗状态,1.8V 区域的所有时钟都被关闭,相应的外设都停止了工作,但它会保留内核寄存器以及 SRAM 的内容;在待机模式下,整个 1.8V 域都断电,该区域的内核寄存器及 SRAM 内容都会丢失 (备份区域的寄存器不受影响)。
(3) 备份域电路(后备供电区域)
STM32 的 LSE 振荡器、RTC 及备份寄存器这些器件被包含进备份域电路中,这部分的电路可以通过 STM32 的 VBAT 引脚获取供电电源,在实际应用中一般会使用 3V 的钮扣电池对该引脚供电。
1.3 STM32 的功耗模式
1.3.1 睡眠模式
1.3.2 停止模式
1.3.3 待机模式
注意:以上睡眠模式、停止模式及待机模式中,若备份域电源正常供电,备份域内的 RTC 都可以正常运行,备份域内的寄存器的数据会被保存,不受功耗模式影响。
41.2 电源管理相关的库函数及命令
2.1 配置 PVD 监控功能
2.2 WFI 与 WFE 命令
2.3 进入停止模式
2.4 进入待机模式
41.3 PWR—睡眠模式实验
3.1 硬件设计
3.2 软件设计
3.2.1 程序设计要点
(1) 初始化用于唤醒的中断按键;
(2) 进入睡眠状态;
(3) 使用按键中断唤醒芯片;
3.2.2 代码分析
(1)main 函数
/**
#include "stm32f10x.h"
#include "./led/bsp_led.h"
#include "./usart/bsp_usart.h"
#include "./Key/bsp_exti.h"
static void Delay(__IO u32 nCount);
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
LED_GPIO_Config();
/*初始化USART1*/
USART_Config();
/* 初始化按键为中断模式,按下中断后会进入中断服务函数 */
EXTI_Key_Config();
printf("rn 欢迎使用野火 STM32 开发板。rn");
printf("rn 野火STM32 睡眠模式例程rn");
printf("rn 实验说明:rn");
printf("rn 1.本程序中,绿灯表示STM32正常运行,红灯表示睡眠状态,蓝灯表示刚从睡眠状态被唤醒rn");
printf("rn 2.程序运行一段时间后自动进入睡眠状态,在睡眠状态下,可使用KEY1或KEY2唤醒rn");
printf("rn 3.本实验执行这样一个循环:rn ------》亮绿灯(正常运行)->亮红灯(睡眠模式)->按KEY1或KEY2唤醒->亮蓝灯(刚被唤醒)-----》rn");
printf("rn 4.在睡眠状态下,DAP下载器无法给STM32下载程序,rn 可按KEY1、KEY2唤醒后下载,rn 或按复位键使芯片处于复位状态,然后在电脑上点击下载按钮,再释放复位按键,即可下载rn");
while(1)
{
/*********执行任务***************************/
printf("rn STM32正常运行,亮绿灯rn");
LED_GREEN;
Delay(0x3FFFFF);
/*****任务执行完毕,进入睡眠降低功耗***********/
printf("rn 进入睡眠模式,按KEY1或KEY2按键可唤醒rn");
//使用红灯指示,进入睡眠状态
LED_RED;
//进入睡眠模式
__WFI(); //WFI指令进入睡眠
//等待中断唤醒 K1或K2按键中断
/***被唤醒,亮蓝灯指示***/
LED_BLUE;
Delay(0x1FFFFF);
printf("rn 已退出睡眠模式rn");
//继续执行while循环
}
}
static void Delay(__IO uint32_t nCount) //简单的延时函数
{
for(; nCount != 0; nCount--);
}
/*********************************************END OF FILE**********************/
其他配置:
41.4 PWR—停止模式实验
4.1 硬件设计
4.2 软件设计
4.2.1 程序设计要点
(1) 初始化用于唤醒的中断按键;
(2) 选择电压调节器的工作模式并进入停止状态;
(3) 使用按键中断唤醒芯片;
(4) 重启 HSE 时钟,使系统完全恢复停止前的状态。
4.2.2 代码分析
(1)重启 HSE 时钟
(2)main函数
/**
#include "stm32f10x.h"
#include "./led/bsp_led.h"
#include "./key/bsp_exti.h"
#include "./usart/bsp_usart.h"
static void Delay(__IO u32 nCount);
static void SYSCLKConfig_STOP(void);
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
RCC_ClocksTypeDef clock_status_wakeup,clock_status_config;
uint8_t clock_source_wakeup,clock_source_config;
LED_GPIO_Config();
/*初始化USART1*/
USART_Config();
/* 初始化按键中断,按下按键后会进入中断服务程序 */
EXTI_Key_Config();
printf("rn 欢迎使用野火 STM32 开发板。rn");
printf("rn 野火STM32 停止模式例程rn");
printf("rn 实验说明:rn");
printf("rn 1.本程序中,绿灯表示STM32正常运行,红灯表示停止状态,蓝灯表示刚从停止状态被唤醒rn");
printf("rn 2.在停止状态下,可使用KEY1或KEY2唤醒rn");
printf("rn 3.本实验执行这样一个循环:rn ------》亮绿灯(正常运行)->亮红灯(停止模式)->按KEY1或KEY2唤醒->亮蓝灯(刚被唤醒)-----》rn");
printf("rn 4.在停止状态下,DAP下载器无法给STM32下载程序,rn 可按KEY1、KEY2唤醒后下载,rn 或按复位键使芯片处于复位状态,然后在电脑上点击下载按钮,再释放复位按键,即可下载rn");
while(1)
{
/*********执行任务***************************/
printf("rn STM32正常运行,亮绿灯rn");
LED_GREEN;
Delay(0x3FFFFF);
/*****任务执行完毕,进入停止降低功耗***********/
printf("rn 进入停止模式,按KEY1或KEY2按键可唤醒rn");
//使用红灯指示,进入停止状态
LED_RED;
/* 进入停止模式,设置电压调节器为低功耗模式,等待中断唤醒 */
PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);
//等待中断唤醒 K1或K2按键中断
/*********************被唤醒***********************/
//获取刚被唤醒时的时钟状态
//时钟源
clock_source_wakeup = RCC_GetSYSCLKSource ();
//时钟频率
RCC_GetClocksFreq(&clock_status_wakeup);
//从停止模式下被唤醒后使用的是HSI时钟,此处重启HSE时钟,使用PLLCLK
SYSCLKConfig_STOP();
//获取重新配置后的时钟状态
//时钟源
clock_source_config = RCC_GetSYSCLKSource ();
//时钟频率
RCC_GetClocksFreq(&clock_status_config);
//因为刚唤醒的时候使用的是HSI时钟,会影响串口波特率,输出不对,所以在重新配置时钟源后才使用串口输出。
printf("rn重新配置后的时钟状态:rn");
printf(" SYSCLK频率:%d,rn HCLK频率:%d,rn PCLK1频率:%d,rn PCLK2频率:%d,rn 时钟源:%d (0表示HSI,8表示PLLCLK)n",
clock_status_config.SYSCLK_Frequency,
clock_status_config.HCLK_Frequency,
clock_status_config.PCLK1_Frequency,
clock_status_config.PCLK2_Frequency,
clock_source_config);
printf("rn刚唤醒的时钟状态:rn");
printf(" SYSCLK频率:%d,rn HCLK频率:%d,rn PCLK1频率:%d,rn PCLK2频率:%d,rn 时钟源:%d (0表示HSI,8表示PLLCLK)n",
clock_status_wakeup.SYSCLK_Frequency,
clock_status_wakeup.HCLK_Frequency,
clock_status_wakeup.PCLK1_Frequency,
clock_status_wakeup.PCLK2_Frequency,
clock_source_wakeup);
/*指示灯*/
LED_BLUE;
Delay(0x1FFFFF);
printf("rn 已退出停止模式rn");
//继续执行while循环
}
}
static void Delay(__IO uint32_t nCount) //简单的延时函数
{
for(; nCount != 0; nCount--);
}
/**
* @brief 停机唤醒后配置系统时钟: 使能 HSE, PLL
* 并且选择PLL作为系统时钟.
* @param None
* @retval None
*/
static void SYSCLKConfig_STOP(void)
{
/* After wake-up from STOP reconfigure the system clock */
/* 使能 HSE */
RCC_HSEConfig(RCC_HSE_ON);
/* 等待 HSE 准备就绪 */
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET)
{
}
/* 使能 PLL */
RCC_PLLCmd(ENABLE);
/* 等待 PLL 准备就绪 */
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* 选择PLL作为系统时钟源 */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* 等待PLL被选择为系统时钟源 */
while (RCC_GetSYSCLKSource() != 0x08)
{
}
}
/*********************************************END OF FILE**********************/
其他配置:
41.5 PWR—待机模式实验
5.1 硬件设计
5.2 软件设计
5.2.1 程序设计要点
(1) 清除 WUF 标志位;
(2) 使能 WKUP 唤醒功能;
(3) 进入待机状态。
5.2.2 代码分析
(1)main 函数
/**
#include "stm32f10x.h"
#include "./led/bsp_led.h"
#include "./key/bsp_key.h"
#include "./usart/bsp_usart.h"
static void Delay(__IO u32 nCount);
static uint8_t KEY2_LongPress(void);
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
/* 使能电源管理单元的时钟,必须要使能时钟才能进入待机模式 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);
LED_GPIO_Config();
/*初始化USART1*/
USART_Config();
/*初始化按键,不需要中断,仅初始化KEY2即可,只用于唤醒的PA0引脚不需要这样初始化*/
Key_GPIO_Config();
printf("rn 欢迎使用野火 STM32 开发板。rn");
printf("rn 野火STM32 待机模式例程rn");
printf("rn 实验说明:rn");
printf("rn 1.本程序中,绿灯表示本次复位是上电或引脚复位,红灯表示即将进入待机状态,蓝灯表示本次是待机唤醒的复位rn");
printf("rn 2.长按KEY2按键后,会进入待机模式rn");
printf("rn 3.在待机模式下,按KEY1按键可唤醒,唤醒后系统会进行复位,程序从头开始执行rn");
printf("rn 4.可通过检测WU标志位确定复位来源rn");
printf("rn 5.在待机状态下,DAP下载器无法给STM32下载程序,需要唤醒后才能下载");
//检测复位来源
if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET)
{
LED_BLUE;
printf("rn 待机唤醒复位 rn");
}
else
{
LED_GREEN;
printf("rn 非待机唤醒复位 rn");
}
while(1)
{
// K2 按键长按进入待机模式
if(KEY2_LongPress())
{
printf("rn 即将进入待机模式,进入待机模式后可按KEY1唤醒,唤醒后会进行复位,程序从头开始执行rn");
LED_RED;
Delay(0x4FFFF);
/*清除WU状态位*/
PWR_ClearFlag (PWR_FLAG_WU);
/* 使能WKUP引脚的唤醒功能 ,使能PA0*/
PWR_WakeUpPinCmd (ENABLE);
/* 进入待机模式 */
PWR_EnterSTANDBYMode();
}
}
}
static void Delay(__IO uint32_t nCount) //简单的延时函数
{
for(; nCount != 0; nCount--);
}
/**
* @brief 用于检测按键是否被长时间按下
* @param 无
* @retval 1 :按键被长时间按下 0 :按键没有被长时间按下
*/
static uint8_t KEY2_LongPress(void)
{
uint8_t downCnt =0; //记录按下的次数
uint8_t upCnt =0; //记录松开的次数
while(1) //死循环,由return结束
{
Delay(0x2FFFF); //延迟一段时间再检测
if(GPIO_ReadInputDataBit ( KEY2_GPIO_PORT, KEY2_GPIO_PIN ) == SET) //检测到按下按键
{
downCnt++; //记录按下次数
upCnt=0; //清除按键释放记录
if(downCnt>=100) //按下时间足够
{
return 1; //检测到按键被时间长按下
}
}
else
{
upCnt++; //记录释放次数
if(upCnt>5) //连续检测到释放超过5次
{
return 0; //按下时间太短,不是按键长按操作
}
}// if(GPIO_ReadInputDataBit
}//while
}
/*********************************************END OF FILE**********************/
其他配置:
41.6 PWR—PVD 电源监控实验
6.1 硬件设计
6.2 软件设计
6.2.1 程序设计要点
6.2.2 代码分析
(1)初始化 PVD
(2)PVD 中断服务函数
(3)main 函数
/**
#include "stm32f10x.h"
#include "./led/bsp_led.h"
#include "./key/bsp_key.h"
#include "./usart/bsp_usart.h"
#include "./pvd/bsp_pvd.h"
/*
*【 !】实验操作:
* 1.使用外部可调电源,调节成5V输出,连接到实验板引出的 5V<--->GND排针给板子供电;
*2.复位实验板,电压正常时板子上的LED彩灯应为绿色
*3.向下调节可调电源的电压,大约当降至4.2V的时候,LED彩灯会转为红色。
*(程序中控制PVD监控电压约为2.6V,当5V电源降至4.2V的时候,连接STM32的VDD电源(3.3V电源)会低于2.5V,产生PVD事件,在中断中控制亮红灯)
*/
/*【 !!】注意事项:
*使用可调电源给实验板供电,其它电源线都拔掉(包括下载器、USB线)。
*由于直接接排针供电没有电路保护,调节电源时小心不要使供电电压远高于5V,电压太高会烧坏实验板!!
*/
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
LED_GPIO_Config();
//亮绿灯,表示正常运行
LED_GREEN;
//配置PVD,当电压过低时,会进入中断服务函数,亮红灯
PVD_Config();
while(1)
{
/*正常运行的程序*/
}
}
/*********************************************END OF FILE**********************/
温馨提示:详情请看《stm32实战开发指南》
最后
以上就是单身康乃馨为你收集整理的第41章 电源管理—实现低功耗的全部内容,希望文章能够帮你解决第41章 电源管理—实现低功耗所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复