STM32电源管理—实现低功耗

注: 本文是学习野火的指南针开发板过程的学习笔记,可能有误,详细请看B站野火官方配套视频教程(这个教程真的讲的很详细,请给官方三连吧)

在响应绿色发展的同时,在很多应用场合中都对电子设备的功耗要求非常苛刻,如某些传感器信息采集设备,仅靠小型的电池提供电源,要求工作长达数年之久,且期间不需要任何维护;由于智慧穿戴设备的小型化要求,电池体积不能太大导致容量也比较小,所以也很有必要从控制功耗入手,提高设备的续行时间。

 01 STM32的电源管理简介

STM32有专门的电源管理外设监控电源并管理设备的运行模式,确保系统正常运行,并尽量降低器件的功耗。

电源监控器:

STM32芯片主要通过引脚VDD从外部获取电源,在它的内部具有电源监控器用于检测VDD的电压,以实现复位功能及掉电紧急处理功能,保证系统可靠地运行。

1. 上电复位与掉电复位(POR与PDR)

POR、PDR功能是使用其电压阈值与外部供电电压VDD比较,当低于工作阈值时,会直接进入复位状态,这可防止电压不足导致的误操作

当检测到VDD的电压低于阈值VPOR及VPDR时(无需外部电路辅助)STM32芯片会自动保持在复位状态,防止因电压不足强行工作而带来严重的后果。在刚开始电压低于VPOR时(约1.92V),STM32保持在上电复位状态(POR,Power On Reset),当VDD电压持续上升至大于VPOR时,芯片开始正常运行,而在芯片正常运行的时候,当检测到VDD电压下降至低于VPDR阈值(约1.88V),会进入掉电复位状态(PDR,Power Down Reset)。

2.可编程电压检测器PVD

STM32还提供了可编程电压检测器PVD,它也是实时检测VDD的电压

当检测到电压低于编程的VPVD阈值时,会向内核产生一个PVD中断(EXTI16线中断)以使内核在复位前进行紧急处理。该电压阈值可通过电源控制寄存器PWR_CSR设置。

使用PVD可配置8个等级,如下表。其中的上升沿和下降沿分别表示类似前面图中的VDD电压上升过程及下降过程的阈值:

阈值等级

条件

最小值

典型值

最大值

单位

级别0

上升沿

2.1

2.18

2.26

V

下降沿

2

2.08

2.16

V

级别1

上升沿

2.19

2.28

2.37

V

下降沿

2.09

2.18

2.27

V

级别2

上升沿

2.28

2.38

2.48

V

下降沿

2.18

2.28

2.38

V

级别3

上升沿

2.38

2.48

2.58

V

下降沿

2.28

2.38

2.48

V

级别4

上升沿

2.47

2.58

2.69

V

下降沿

2.37

2.48

2.59

V

级别5

上升沿

2.57

2.68

2.79

V

下降沿

2.47

2.58

2.69

V

级别6

上升沿

2.66

2.78

2.9

V

下降沿

2.56

2.68

2.8

V

级别7

上升沿

2.76

2.88

3

V

下降沿

2.66

2.78

2.9

V

 STM32的电源系统:

为了方便进行电源管理,STM32把它的外设、内核等模块跟据功能划分了供电区域,其内部电源区域划分如图:

  STM32的电源系统主要分为备份域电路、内核电路以及ADC电路三部分,介绍如下:

  • ADC电源及参考电压(VDDA供电区域):
    为了提高转换精度,STM32的ADC配有独立的电源接口,方便进行单独的滤波。ADC的工作电源使用VDDA引脚输入,使用VSSA作为独立的地连接,VREF引脚则为ADC提供测量使用的参考电压。
  • 调压器供电电路( V DD /1.8V 供电区域):
    STM32 的电源系统中调压器供电的电路是最主要的部分,调压器为备份域及待机电路的所有数字电路供电,其中包括内核、数字外设以及 RAM ,调压器的输出电压约为 1.8V ,因而使用调压器供电的这些电路区域被称为 1.8V 域。
调压器可以运行在“运行模式”、“停止模式”以及“待机模式”。在运行模式下,1.8域全功率运行;在停止模式下 1.8V 域运行在低功耗状态,1.8V 区域的所有时钟都关闭,相应的外设都停止了工作,但它会保留内核寄存器以及 SRAM 的内容;在机模式下,整个 1.8V 域都断电,该区域的内核寄存器及 SRAM 内容都会丢失 (备区域的寄存器不受影响)。
  • 备份域电路(后备供电区域):     
    STM32的LSE振荡器、RTC及备份寄存器这些器件被包含进备份域电路中,这部分的电路可以通过STM32的VBAT引脚获取供电电源,在实际应用中一般会使用3V的钮扣电池对该引脚供电。

 在图中后备供电区域的左侧有一个电源开关结构,它的功能类似下图的双二极管,在它的“1”处连接了VBAT电源,“2”处连接了VDD主电源(一般为3.3V),右侧“3”处引出到备份域电路中。当VDD主电源存在时,由于VDD电压较高,备份域电路通过VDD供电,节省钮扣电池的电源,仅当VDD掉电时,备份域电路由钮扣电池通过VBAT供电,保证电路能持续运行,从而可利用它保留关键数据。


02 STM32的功耗模式 

按功耗由高到低排列,STM32具有运行、睡眠、停止和待机四种工作模式。上电复位后STM32处于运行状态时,当内核不需要继续运行,就可以选择进入后面的三种低功耗模式降低功耗,这三种模式中,电源消耗不同、唤醒时间不同、唤醒源不同,用户需要根据应用需求,选择最佳的低功耗模式。

这三种低功耗模式层层递进,运行的时钟或芯片功能越来越少,因而功耗越来越低。

 1.睡眠模式

在睡眠模式中,仅关闭了内核时钟,内核停止运行,但其片上外设,CM3核心的外设全都还照常运行。     有两种方式进入睡眠模式,它的进入方式决定了从睡眠唤醒的方式,分别是WFI(wait for interrupt)和WFE(wait for event),即由等待“中断”唤醒和由“事件”唤醒。睡眠模式的各种特性见下表:

2.停止模式 

在停止模式中,进一步关闭了其它所有的时钟,于是所有的外设都停止了工作,但由于其1.8V区域的部分电源没有关闭,还保留了内核的寄存器、内存的信息,所以从停止模式唤醒,并重新开启时钟后,还可以从上次停止处继续执行代码。停止模式可以由任意一个外部中断(EXTI)唤醒,在停止模式中可以选择电压调节器为开模式或低功耗模式。停止模式的各种特性见下表:

3.待机模式

 待机模式,它除了关闭所有的时钟,还把1.8V区域的电源也完全关闭了,也就是说,从待机模式唤醒后,由于没有之前代码的运行记录,只能对芯片复位,重新检测boot条件,从头开始执行程序。它有四种唤醒方式,分别是WKUP(PA0)引脚的上升沿,RTC闹钟事件,NRST引脚的复位和IWDG(独立看门狗)复位。

在以上讲解的睡眠模式、停止模式及待机模式中,若备份域电源正常供电,备份域内的RTC都可以正常运行,备份域内的寄存器的数据会被保存,不受功耗模式影响。 


03电源管理相关的库函数及命令

STM32标准库对电源管理提供了完善的函数及命令,使用它们可以方便地进行控制。

配置PVD监控功能

PVD可监控VDD的电压,当它低于阈值时可产生PVD中断以让系统进行紧急处理,这个阈值可以直接使用库函数PWR_PVDLevelConfig配置成前面阈值表中说明的阈值等级。

进入睡眠——WFI与WFE命令

在前面可了解到进入各种低功耗模式时都需要调用WFI或WFE命令,它们实质上都是内核指令,在库文件core_cm3.h中把这些指令封装成了函数:

对于这两个指令,应用时只需要知道,调用它们都能进入低功耗模式,需要使用函数的格式“__WFI();”和“__WFE();”来调用(因为__wfi及__wfe是编译器内置的函数,函数内部使用调用了相应的汇编指令)。

进入停止模式

直接调用WFI和WFE指令可以进入睡眠模式,而进入停止模式则还需要在调用指令前设置一些寄存器位,STM32标准库把这部分的操作封装到PWR_EnterSTOPMode函数中了,它的定义如下:

1 /**
2 * @brief 进入停止模式
3 *
4 * @note 在停止模式下所有 I/O 的会保持在停止前的状态
5 * @note 从停止模式唤醒后,会使用 HSI 作为时钟源
6 * @note 调压器若工作在低功耗模式,可减少功耗,但唤醒时会增加延迟
7 * @param PWR_Regulator: 设置停止模式时调压器的工作模式
8 * @arg PWR_MainRegulator_ON: 调压器正常运行
9 * @arg PWR_Regulator_LowPower: 调压器低功耗运行
10 * @param PWR_STOPEntry: 设置使用 WFI 还是 WFE 进入停止模式
11 * @arg PWR_STOPEntry_WFI: WFI 进入停止模式
12 * @arg PWR_STOPEntry_WFE: WFE 进入停止模式13 * @retval None
14 */
15 void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
16 {
17 uint32_t tmpreg = 0;
18 /* 检查参数 */
19 assert_param(IS_PWR_REGULATOR(PWR_Regulator));
20 assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
21
22 /* 设置调压器的模式 ------------*/
23 tmpreg = PWR->CR;
24 /* 清除 PDDS 及 LPDS 位 */
25 tmpreg &= CR_DS_MASK;
26 /* 根据 PWR_Regulator 的值 (调压器工作模式) 配置 LPDS,MRLVDS 及 LPLVDS 位 */
27 tmpreg |= PWR_Regulator;
28 /* 写入参数值到寄存器 */
29 PWR->CR = tmpreg;
30 /* 设置内核寄存器的 SLEEPDEEP 位 */
31 SCB->SCR |= SCB_SCR_SLEEPDEEP;
32
33 /* 设置进入停止模式的方式-----------------*/
34 if (PWR_STOPEntry == PWR_STOPEntry_WFI) {
35 /* 需要中断唤醒 */
36 __WFI();
37 } else {
38 /* 需要事件唤醒 */
39 __WFE();
40 }
41
42 /* 以下的程序是当重新唤醒时才执行的,清除 SLEEPDEEP 位的状态 */
43 SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
44 }

        这个函数有两个输入参数,分别用于控制调压器的模式及选择使用WFI或WFE停止,代码中先是根据调压器的模式配置PWR_CR寄存器,再把内核寄存器的SLEEPDEEP位置1,这样再调用WFI或WFE命令时,STM32就不是睡眠,而是进入停止模式了。函数结尾处的语句用于复位SLEEPDEEP位的状态,由于它是在WFI及WFE指令之后的,所以这部分代码是在STM32被唤醒的时候才会执行。     

        要注意的是进入停止模式后,STM32的所有I/O都保持在停止前的状态,而当它被唤醒时,STM32使用HSI作为系统时钟(8MHz)运行,由于系统时钟会影响很多外设的工作状态,所以一般我们在唤醒后会重新开启HSE,把系统时钟设置回原来的状态。

进入待机模式

STM32标准库也提供了控制进入待机模式的函数,其定义如下:

1 /**
2 * @brief 进入待机模式
3 * @note 待机模式时,除以下引脚,其余引脚都在高阻态:
4 * -复位引脚
5 * - RTC_AF1 引脚 (PC13) (需要使能侵入检测、时间戳事件或 RTC 闹钟事件)
6 * - RTC_AF2 引脚 (PI8) (需要使能侵入检测或时间戳事件)
7 * - WKUP 引脚 (PA0) (需要使能 WKUP 唤醒功能)
8 * @note 在调用本函数前还需要清除 WUF 寄存器位
9 * @param None
10 * @retval None
11 */
12 void PWR_EnterSTANDBYMode(void)
13 {
14 /* 清除 Wake-up 标志 */
15 PWR->CR |= PWR_CR_CWUF;
16 /* 选择待机模式 */
17 PWR->CR |= PWR_CR_PDDS;
18 /* 设置内核寄存器的 SLEEPDEEP 位 */
19 SCB->SCR |= SCB_SCR_SLEEPDEEP;
20 /* 存储操作完毕时才能进入待机模式,使用以下语句确保存储操作执行完毕 */
21 #if defined ( __CC_ARM )
22 __force_stores();
23 #endif
24 /* 等待中断唤醒 */
25 __WFI();
26 }

该函数中先配置了PDDS寄存器位及SLEEPDEEP寄存器位,接着调用__force_stores函数确保存储操作完毕后再调用WFI指令,从而进入待机模式。这里值得注意的是,待机模式也可以使用WFE指令进入的,如果您有需要可以自行修改。     在进入待机模式后,除了被使能了的用于唤醒的I/O,其余I/O都进入高阻态,而从待机模式唤醒后,相当于复位STM32芯片,程序重新从头开始执行。


 04电源管理实验

PWR—睡眠模式(如何控制 STM32 进入低功耗睡眠模式。

程序设计:

int main()
{(1) 初始化用于唤醒的中断按键;
…………………………………………………………………… 
while(1){	/*********执行任务***************************/printf("\r\n STM32正常运行,亮绿灯\r\n");LED_GREEN;	Delay(0x3FFFFF);
(2) 进入睡眠状态;/*****任务执行完毕,进入睡眠降低功耗***********/printf("\r\n 进入睡眠模式,按KEY1或KEY2按键可唤醒\r\n");//使用红灯指示,进入睡眠状态LED_RED;//进入睡眠模式__WFI();	//WFI指令进入睡眠(3) 使用按键中断唤醒芯片;//由于 WFI 睡眠模式可以使用任意中断唤醒,所以我们可以使用按键中断唤醒。//等待中断唤醒  K1或K2按键中断	/***被唤醒,亮蓝灯指示***/LED_BLUE;	Delay(0x1FFFFF);		printf("\r\n 已退出睡眠模式\r\n");//继续执行while循环}
}
/*按键中断部分*/
void KEY1_IRQHandler(void)
{//确保是否产生了EXTI Line中断if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) {LED_BLUE;		printf("\r\n KEY1 按键中断唤醒 \r\n");    EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     }  
}void KEY2_IRQHandler(void)
{//确保是否产生了EXTI Line中断if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) {LED_BLUE;printf("\r\n KEY2 按键中断唤醒 \r\n");   //清除中断标志位EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     }  
}
注意 : 当系统处于睡眠模式低功耗状态时 ( 包括后面讲解的停止模式及待机模式 ) ,使用 DAP下载器是无法给芯片下载程序的,所以下载程序时要先把系统唤醒。或者使用如下方法:按着板子的复位按键,使系统处于复位状态,然后点击电脑端的下载按钮下载程序,这时再释放复位按键,就能正常给板子下载程序了。

PWR—停止模式实验(解如何进入停止模式及唤醒后的状态恢复。

与睡眠模式不一样,系统从停止模式被唤醒时,是使用 HSI 作为系统时钟的,在 STM32F103 中, HSI 时钟一般为 8MHz ,与我们常用的 72MHz 相关太远,它会影响各种外设的工作频率。所以在系统从停止模式唤醒后,若希望各种外设恢复正常的工作状态,就要恢复停止模式前使用的系统时钟,本实验中定义了一个 SYSCLKConfig_STOP 函数,用于恢复系统时钟:
/*** @brief  停机唤醒后配置系统时钟:
这个函数主要是调用了各种 RCC 相关的库函数,
开启了 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){}
}

main函数部分

/* 进入停止模式,设置电压调节器为低功耗模式,等待中断唤醒 */PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);	
由于 WFI 停止模式可以使用任意 EXTI 的中断唤醒,所以我们可以 使用按键中断唤醒
void KEY_IRQHandler(void)
{//确保是否产生了EXTI Line中断if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) {LED_BLUE;//由于停止唤醒后使用的是HSI时钟,与原来使用的HSE时钟时的频率不一致,会影响波特率,若此处直接printf会乱码//printf("\r\n KEY2 按键中断唤醒 \r\n");   //清除中断标志位EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     }  
}
当执行完中断服务函数后,会继续执行 WFI 指令 ( PWR_EnterSTOPMode 函数 ) 后的代码。

为了更清晰地展示停止模式的影响,在刚唤醒后,我们定义了

	RCC_ClocksTypeDef clock_status_wakeup,clock_status_config;uint8_t clock_source_wakeup,clock_source_config; 

用于调用库函数 RCC_GetSYSCLKSourc以及 RCC_GetClocksFreq 获取刚唤醒后的系统的时钟源以及时钟频率,在使用 SYSCLKCon-fig_STOP 恢复时钟后,我们再次获取这些时状态,最后再通过串口打印出来。

//获取刚被唤醒时的时钟状态	//时钟源clock_source_wakeup = RCC_GetSYSCLKSource ();//时钟频率RCC_GetClocksFreq(&clock_status_wakeup);//从停止模式下被唤醒后使用的是HSI时钟,此处重启HSE时钟,使用PLLCLKSYSCLKConfig_STOP();//获取重新配置后的时钟状态	//时钟源clock_source_config = RCC_GetSYSCLKSource ();//时钟频率RCC_GetClocksFreq(&clock_status_config);
//因为刚唤醒的时候使用的是HSI时钟,会影响串口波特率,输出不对,所以在重新配置时钟源后才使用串口输出。printf("\r\n重新配置后的时钟状态:\r\n");printf(" SYSCLK频率:%d,\r\n HCLK频率:%d,\r\n PCLK1频率:%d,\r\n PCLK2频率:%d,\r\n 时钟源:%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("\r\n刚唤醒的时钟状态:\r\n");	printf(" SYSCLK频率:%d,\r\n HCLK频率:%d,\r\n PCLK1频率:%d,\r\n PCLK2频率:%d,\r\n 时钟源:%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);
通过串口调试信息我们会知道刚唤醒时系统时钟使用的是 HSI 时钟,频率为 8MHz ,恢复后的系统时钟采用 HSE 倍频后的 PLL 时钟,时钟频率为 72MHz

PWR—待机模式实验 最低功耗的待机模式

要强调的是,由于 WKUP 引脚 (PA0) 必须使用上升沿才能唤醒待机状态的系统,所以我们硬件设计的 PA0 引脚连接到按键 KEY1 ,且按下按键的时候会在 PA0 引脚产生上升沿,从而可实现唤醒的功能,按键的具体电路请查看配套的原理图。
1.程序首先使用库函数 RCC_APB1PeriphClockCmd 和参数 RCC_APB1Periph_PWR 初始化了源管理外设的时钟,要先使能该时钟,后面才能正常使用命令进入待机状态和唤醒。
	/* 使能电源管理单元的时钟,必须要使能时钟才能进入待机模式 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);
2.由于待机模式唤醒使用 WKUP 引脚并不需要特别的引脚初始化,所以我们调用普通的按键初始化函数即可(模式的 WKUP 唤醒不需要中断,也不需要像按键那样初始化)
int main(void)
{	/* 使能电源管理单元的时钟,必须要使能时钟才能进入待机模式 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);//检测复位来源if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET){LED_BLUE;printf("\r\n 待机唤醒复位 \r\n");}else{LED_GREEN;printf("\r\n 非待机唤醒复位 \r\n");}while(1){}
}
3.在使用库函数 PWR_EnterSTANDBYMode发送待机命令前,要先使用库函数 PWR_ClearFlag 清除 PWR_FLAG_WU 标志位,并且使用库函数 PWR_WakeUpPinCmd 使能 WKUP 唤醒功能,这样进入待机模式后才能使用 WKUP 唤醒。
	/*清除WU状态位*/PWR_ClearFlag (PWR_FLAG_WU);/* 使能WKUP引脚的唤醒功能 ,使能PA0*/PWR_WakeUpPinCmd (ENABLE);/* 进入待机模式 */PWR_EnterSTANDBYMode();
在进入待机模式前我们控制了 LED 彩灯为红色,但在待机状态时,由于 I/O 口会处于高阻态,所以 LED 灯会熄灭。
按下 KEY1 按键,会使 PA0 引脚产生一个上升沿,从而唤醒系统。
系统唤醒后会进行复位,从头开始执行上述过程,与第一次上电时不同的是,这样的复位会使 PWR_FLAG_WU 标志位改为 SET 状态,所以这个时候 LED 彩灯会亮蓝色。(这也为什么我们可以从while循环外获取是否是待机启动)

PWRPVD 电源监控实验(如何使用 PVD 监控供电电源,增强系统的鲁棒性

中使用 PVD 监控 STM32 芯片的 VDD 引脚,当监测到供电电压低于阈值时会产生 PVD 中断,系统进入中断服务函数进入紧急处理过程。所以进行这个实验时需要使用一个可调的电压源给实验板供电,改变给 STM32 芯片的供电电压,为此我们需要先了解实验板的电源供电系统,见图实验板的电源供电系统

整个电源供电系统主要分为以下五部分:

  • (1) 6-12V DC 电源供电系统,这部分使用 DC 电源接口引入 6-12V 的电源,经过 RT7272 进行电压转换成 5V 电源,再与第二部分的“5V_USB”电源线连接在一起。
  • (2) 第二部分使用 USB 接口,使用 USB 线从外部引入 5V 电源,引入的电源经过电源开关及保险丝连接到“5V”电源线。
  • (3) 第三部分的是电源开关及保险丝,即当我们的实验板使用 DC 电源或“5V_USB”线供电时,可用电源开关控制通断,保险丝也会起保护作用。
  • (4) 5V”电源线遍布整个板子,板子上各个位置引出的标有“5V”丝印的排针都与这个电源线直接相连。5V 电源线给板子上的某些工作电压为 5V 的芯片供电。5V 电源还经过 LDO 稳压芯片,输出 3.3V 电源连接到“3.3V”电源线。
  • (5) 同样地,“3.3V”电源线也遍布整个板子,各个引出的标有“3.3V”丝印的排针都与它直接相连,3.3V 电源给工作电压为 3.3V 的各种芯片供电。STM32 芯片的 VDD 引脚就是直接与这个3.3V 电源相连的,所以通过 STM32 PVD 监控的就是这个“3.3V”电源线的电压。

当我们进行这个 PVD 实验时,为方便改变“ 3.3V ”电源线的电压,我们可以把可调电源通过实
验板上引出的“ 5V ”及“ GND ”排针给实验板供电,当可调电源电压降低时, LDO 在“ 3.3V ”电
源线的供电电压会随之降低,即 STM32 PVD 监控的 VDD 引脚电压会降低,这样我们就可以
模拟 VDD 电压下降的实验条件,对 PVD 进行测试了。不过,由于这样供电不经过保险丝,所以
在调节电压的时候要小心,不要给它供电远高于 5V ,否则可能会烧坏实验板上的芯片。

软件设计:

初始化 PVD
使用 PVD 功能前需要先初始化,我们把这部分代码封装到 PVD_Config 函数中
/*** @brief  配置PVD.* @param  None* @retval None*/
void PVD_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;/*使能 PWR 时钟 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);/* 使能 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);/* 配置 EXTI16线(PVD 输出) 来产生上升下降沿中断*/EXTI_ClearITPendingBit(EXTI_Line16);EXTI_InitStructure.EXTI_Line = EXTI_Line16;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);/* 配置PVD级别PWR_PVDLevel_2V6 (PVD检测电压的阈值为2.6V,VDD电压低于2.6V时产生PVD中断) *//*具体级别根据自己的实际应用要求配置*/PWR_PVDLevelConfig(PWR_PVDLevel_2V6);/* 使能PVD输出 */PWR_PVDCmd(ENABLE);
}
在这段代码中,执行的流程如下:
(1) 配置 PVD 的中断优先级。由于电压下降是非常危急的状态,所以请尽量把它配置成最高优先级。
(2) 配置了 EXTI16 线的中断源,设置 EXTI16 是因为 PVD 中断是通过 EXTI16 产生中断的 (GPIO的中断是 EXTI0-EXTI15)
(3) 使用库函数 PWR_PVDLevelConfig 设置 PVD 监控的电压阈值等级,各个阈值等级表示的电压值请查阅表 PVD 的阈值等级 STM32 的数据手册。
(4) 最后使用库函数 PWR_PVDCmd 使能 PVD 功能。
	/*** @brief  PVD中断请求* @param  None* @retval None*/
void PVD_IRQHandler(void)
{/*检测是否产生了PVD警告信号*/if(PWR_GetFlagStatus (PWR_FLAG_PVDO)==SET)			{/* 亮红灯,实际应用中应进入紧急状态处理 */LED_RED; }/* 清除中断信号*/EXTI_ClearITPendingBit(EXTI_Line16);}
注意这个中断服务函数的名是 PVD_IRQHandler 而不是 EXTI16_IRQHandler(STM32 没有这样的中断函数名) ,示例中我们仅点亮了 LED 红灯,不同的应用中要根据需求进行相应的紧急处理。

主函数

本电源监控实验的 main 函数执行流程比较简单,仅调用了 PVD_Config 配置监控功能,当 VDD供电电压正常时,板子亮绿灯,当电压低于阈值时,会跳转到中断服务函数中,板子亮红灯
​int main(void)
{	LED_GPIO_Config();	//亮绿灯,表示正常运行LED_GREEN; //配置PVD,当电压过低时,会进入中断服务函数,亮红灯PVD_Config();while(1){			/*正常运行的程序*/}
}

【 !】实验操作:
 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,电压太高会烧坏实验板!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/474940.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux网络:守护进程

Linux网络&#xff1a;守护进程 会话进程组会话终端 守护进程setsiddaemon 在创建一个网络服务后&#xff0c;往往这个服务进程是一直运行的。但是对于大部分进程来说&#xff0c;如果退出终端&#xff0c;这个终端上创建的所有进程都会退出&#xff0c;这就导致进程的生命周期…

基于深度学习的文本信息提取方法研究(pytorch python textcnn框架)

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

Seatunnel解决Excel中无法将数字类型转换成字符串类型以及源码打包

需求 需要实现将Excel中的数字类型的单元格像数据库中字符串类型的字段中推送 问题原因 Seatunnel在读取字段类型的时候都是使用强转的形式去获取数据的 假如说数据类型不一样的话直接强转就会报错 修改位置 org/apache/seatunnel/api/table/type/SeaTunnelRow.java org…

AntFlow 0.11.0版发布,增加springboot starter模块,一款设计上借鉴钉钉工作流的免费企业级审批流平台

AntFlow 0.11.0版发布,增加springboot starter模块,一款设计上借鉴钉钉工作流的免费企业级审批流平台 传统老牌工作流引擎比如activiti,flowable或者camunda等虽然功能强大&#xff0c;也被企业广泛采用&#xff0c;然后也存着在诸如学习曲线陡峭&#xff0c;上手难度大&#x…

UniAPP快速入门教程(一)

一、下载HBuilder 首先需要下载HBuilder开发工具&#xff0c;下载地址:https://www.dcloud.io/hbuilderx.htmlhttps://www.dcloud.io/hbuilder.html 选择Windows正式版.zip文件下载。下载解压后直接运行解压目录里的HBuilderX.exe就可以启动HBuilder。 UniApp的插件市场网址…

计算机网络 (5)数据通信的基础知识

前言 数据通信是一种以信息处理技术和计算机技术为基础的通信方式&#xff0c;它通过数据通信系统将数据以某种信号方式从一处传送到另一处&#xff0c;为计算机网络的应用和发展提供了技术支持和可靠的通信环境&#xff0c;是现代通信技术的关键部分。 一、数据通信的基本概念…

K8s学习笔记之了解k8s的网络模型

文章目录 docker 网络模型容器与容器之间&#xff0c;容器与宿主机之间如何通信容器访问外部网络外部网络访问容器 k8s 网络模型CNIpod 网络配置流程 k8s 热门网络插件介绍Flannel 来源Calico 来源Cilium 来源 k8s 网络插件的工作模式Flannel 的工作模式Calico 的工作模式BGP 和…

Python 三种方式实现自动化任务

在这篇文章中&#xff0c;我们将介绍一些用Python实现机器人过程自动化的包。机器人流程自动化&#xff08;Robotic process automation&#xff0c;简称RPA&#xff09;是指将鼠标点击和键盘按压自动化的过程&#xff0c;即模拟人类用户的操作。RPA用于各种应用程序&#xff0…

时代变迁对传统机器人等方向课程的巨大撕裂

2020年之后&#xff0c;全面转型新质课程规划&#xff0c;传统课程规划全部转为经验。 农耕-代表性生产关系-封建分配制度主要生产力-人力工业-代表性生产关系-资本分配制度工业分为机械时代&#xff0c;电气时代&#xff0c;信息时代&#xff1b;主要生产力-人力转为人脑&…

流程图图解@RequestBody @RequestPart @RequestParam @ModelAttribute

RequestBody 只能用一次&#xff0c;因为只有一个请求体 #mermaid-svg-8WZfkzl0GPvOiNj3 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-8WZfkzl0GPvOiNj3 .error-icon{fill:#552222;}#mermaid-svg-8WZfkzl0GPvOiNj…

学习记录:js算法(九十九):冗余连接

文章目录 冗余连接思路一 冗余连接 树可以看成是一个连通且 无环 的 无向 图。 给定往一棵 n 个节点 (节点值 1&#xff5e;n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间&#xff0c;且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数…

ISUP协议视频平台EasyCVR私有化部署视频平台如何实现RTMP推流将大疆无人机的视频画面回传?

在现代视频监控和流媒体技术领域&#xff0c;EasyCVR视频融合云平台以其卓越的性能和灵活性&#xff0c;成为了跨区域、网络化视频监控综合管理的理想选择。作为TSINGSEE青犀视频“云边端”架构体系中的核心组件&#xff0c;私有化部署视频平台EasyCVR不仅能够实现视频数据的集…

【Linux】Linux入门实操——进程管理(重点)

1. 概述 在 LINUX 中&#xff0c;每个执行的程序都称为一个进程。每一个进程都分配一个ID号(pid,进程号)。>windows > linux每个进程都可能以两种方式存在的。前台与后台&#xff0c;所谓前台进程就是用户目前的屏幕上可以进行操作的。后台进程则是实际在操作&#xff0…

Postman之安装及汉化基本使用介绍

Postman之安装及汉化 1.安装及汉化postman2.基本使用介绍2.1.基本功能&#xff1a;2.2.编辑、查看、设置环境、全局、集合变量2.3.复制代码片段2.4.运行集合中的所有请求及引用外部文件进行参数化 1.安装及汉化postman 下载安装包 首先可以到官网下载安装包&#xff0c;需要注…

百度AI人脸检测与对比

1.注册账号 打开网站 https://ai.baidu.com/ &#xff0c;注册百度账号并登录 2.创建应用 3.技术文档 https://ai.baidu.com/ai-doc/FACE/yk37c1u4t 4.Spring Boot简单集成测试 pom.xml 配置&#xff1a; <!--百度AI--> <dependency> <groupId>com.baidu.…

基于Java Springboot川剧科普平台

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

用vscode编写verilog时,如何有信号定义提示、信号定义跳转(go to definition)、模块跳转(跨文件跳转)这些功能

&#xff08;一&#xff09;方法一&#xff1a;安装插件SystemVerilog - Language Support 安装一个vscode插件即可&#xff0c;插件叫SystemVerilog - Language Support。虽然说另一个插件“Verilog-HDL/SystemVerilog/Bluespec SystemVerilog”也有信号提示及定义跳转功能&am…

Debezium-EmbeddedEngine

提示&#xff1a;一个嵌入式的Kafka Connect源连接器的工作机制 文章目录 前言一、控制流图二、代码分析 1.构造函数2.完成回调3.连接器回调4.RUN总结 前言 工作机制&#xff1a; * 独立运行&#xff1a;嵌入式连接器在应用程序进程中独立运行&#xff0c;不需要Kafka、Kafka C…

ThreadLocal原理及其内存泄漏

ThreadLocal通过为每个线程创建一个共享变量的副本来保证各个线程之间变量的访问和修改互不影响。 ThreadLocal存放的值是线程内共享的&#xff0c;线程间互斥的&#xff0c;主要用于线程内共享数据&#xff0c;避免通过参数传递。 ThreadLocal有四个方法&#xff1a; initialV…

Java中日志采集框架-JUL、Slf4j、Log4j、Logstash

1. 日志采集 日志采集是指在软件系统、网络设备、服务器或其他IT基础设施中自动收集日志文件和事件信息的过程。这些日志通常包含了时间戳、事件类型、源和目标信息、错误代码、用户操作记录等关键数据。日志采集的目的是为了监控系统运行状态、分析系统性能、审计用户行为、故…