STM32开发(19)----CubeMX配置PWR电源管理


前言

本章介绍使用STM32CubeMX对PWR进行配置的方法,PWR的原理、概念和特点,配置各个步骤的功能,并通过实验方式实现展示结果。

一、什么是PWR?

电源对电子设备的重要性不言而喻,它是保证系统稳定运行的基础,而保证系统能稳定运行后,又有低功耗的要求。在很多应用场合中都对电子设备的功耗要求非常苛刻,如某些传感器信息采集设备,仅靠小型的电池提供电源,要求工作长达数年之久,且期间不需要任何维护;由于智慧穿戴设备的小型化要求,电池体积不能太大导致容量也比较小,所以也很有必要从控制功耗入手,提高设备的续行时间。因此, STM32 有专门的电源管理外设监控电源并管理设备的运行模式,确保系统正常运行,并尽量降低器件的功耗。

PWR分为下列几个部分内容:

1.电源系统

为了方便进行电源管理, STM32 把它的外设、内核等模块跟据功能划分了供电区域
在这里插入图片描述
从上图可知,STM32 的电源系统主要分为备份域供电、内核供电以及 AD/传感器供电三部分:
① AD/传感器电路供电和参考电压
STM32 的 ADC/温度传感器 模块配备独立的供电方式

② 电压调节器
在 STM32 的电源系统中调压器供电的电路是最主要的部分,调压器为备份域及待机电路以外的所有数字电路供电,其中包括内核、数字外设以及 RAM,调压器的输出电压约为 1.8V,因而使用调压器供电的这些电路区域被称为 1.8V 域。调压器可以运行在“运行模式”、“停止模式”以及“待机模式”。在运行模式下, 1.8V域全功率运行;在停止模式下 1.8V 域运行在低功耗状态, 1.8V 区域的所有时钟都被关闭,相应的外设都停止了工作,但它会保留内核寄存器以及 SRAM 的内容;在待机模式下,整个 1.8V 域都断电,该区域的内核寄存器及 SRAM 内容都会丢失 (备份区域的寄存器不受影响)

③ 电池备份区域
电池备份区域也就是后备供电区域,使用电池或者其他电源连接到 VBAT 脚上,当 VDD断电时,可以保存备份寄存器的内容和维持 RTC 的功能。同时 VBAT 引脚也为 RTC 和 LSE 振荡器供电,这保证了当主要电源被切断时, RTC 能够继续工作。切换到 VBAT 供电由复位模块中的掉电复位功能控制。

2.电源监控器

STM32 芯片主要通过引脚 VDD 从外部获取电源,在它的内部具有编程电压检测器(PVD)用于检测 VDD 的电压,以实现复位功能及掉电紧急处理功能,保证系统可靠地运行。
在这里插入图片描述
从上图中可知: POR、 PDR 功能是使用其电压阈值与外部供电电压 VDD 比较,当低于工作阈值时,会直接进入复位状态,这可防止电压不足导致的误操作。除此之外, STM32 还提供了可编程电压检测器 PVD,它也是实时检测 VDD 的电压,当检测到电压低于编程的 VPVD 阈值时,会向内核产生一个 PVD 中断 (EXTI16 线中断) 以使内核在复位前进行紧急处理。

3.电源管理

在 STM32 的除了正常工作外具有三种低功耗模式:睡眠、停止以及待机。在上电复位后, STM32 处于运行状态时,当内核不需要继续运行,就可以选择进入后面的三种模式降低功耗。这三种低功耗模式电源消耗不同、唤醒时间不同和唤醒源不同。
睡眠模式:
在这里插入图片描述
停止模式:
在这里插入图片描述
待机模式:
在这里插入图片描述

二、实验过程

1.STM32CubeMX配置

选择芯片stm32f103c6t6,新建工程
在这里插入图片描述

设置时钟源,最小系统外部晶振8Mhz,作为外部高速HSE时钟源。由于没有外接外部低速晶振,这里低速时钟源选择旁路时钟源。

在这里插入图片描述

配置时钟树,这里使用官方推荐的配置

在这里插入图片描述
配置GPIO中断用于唤醒
在这里插入图片描述
使能中断
在这里插入图片描述
配置串口用于打印测试
在这里插入图片描述
USART1的参数配置如下,波特率115200,传输数据长度为8 Bit,奇偶检验无,停止位1.其他参数默认
在这里插入图片描述
RTC配置
在这里插入图片描述
Code Generator中设置只拷贝使用到的库,分离.c和.h文件
在这里插入图片描述

设置好项目名称和路径,点击GENERATE CODE即可,生成后使用keil5 IDE打开。
在这里插入图片描述

2.代码实现

在usart.c文件后面添加如下代码,代码中添加了#ifdef宏定义进行条件编译,如果使用GUNC编译,则PUTCHAR_PROTOTYPE 定义为int __io_putchar(int ch)函数,否则定义为int fputc(int ch, FILE *f)函数。

/* USER CODE BEGIN 0 */
#include "stdio.h"
#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
    
    
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
 
  return ch;
}
/* USER CODE END 0 */

SLEEP_MODE模式

睡眠模式: 内核停止,程序以WFI指令进入睡眠模式,所以只要产生任意中断都会退出睡眠模式。所以进入睡眠模式前先调用HAL_SuspendTick()函数挂起系统滴答定时器,否则将会被系统滴答定时器(SysTick)中断在1ms内唤醒。程序运行到HAL_PWR_EnterSLEEPMode()函数时,系统进入睡眠模式,程序停止运行。当按下WAKEUP按键时,触发外部中断0,此时系统被唤醒。继续执行HAL_ResumeTick()语句回复系统滴答定时器。

main函数如下:

int main(void)
{
    
    
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_RTC_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  printf("\r\n********    STM32F13c6t6 LowPower Test  *******\r\n");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    printf("Press WAKEUP button to enter LP modes \r\n\r\n");
  
    printf("SleepMode!\r\nPress WAKE_UP button to wake up ...\r\n");
    HAL_SuspendTick();
  
     /* Request to enter SLEEP mode */
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
  
    /* Resume Tick interrupt if disabled prior to sleep mode entry */
    HAL_ResumeTick();
    printf("\r\nSLEEP_MODE wake up,system running continue ... \r\n");
         
}
  /* USER CODE END 3 */
}

实验结果

程序开始,进入低功耗模式,触发中断系统继续执行,运行结果如下
在这里插入图片描述

STOP_MODE模式

停止模式: 内核停止,外设也停止工作,所有外设时钟也关闭。此处设置了RTC唤醒。RTC时钟配置为外部时钟,频率为32.768KHz。经过16分频后的时基为16 /(~32.768KHz) = ~0,488 ms。若要20s后唤醒,则唤醒计数器的值为~20s/0,488ms = 40983 = 0xA017。由于停止模式PLL、HSI、HSE RC振荡器均被禁止,所以系统被唤醒(RTC唤醒或WAKUP按键外部中断唤醒)后需要重新配置系统时钟,同时关闭WAKEUP定时器。
由于外设时钟停止,所以程序返回main()函数中也需要重新初始化串口才能打印输出信息。

/* USER CODE BEGIN 0 */
static void SYSCLKConfig_STOP(void)
{
    
    
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;
  uint32_t pFLatency = 0;
  
  /* Get the Oscillators configuration according to the internal RCC registers */
  HAL_RCC_GetOscConfig(&RCC_OscInitStruct);
  
  /* After wake-up from STOP reconfigure the system clock: Enable HSE and PLL */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    
    
    Error_Handler();
  }

  /* Get the Clocks configuration according to the internal RCC registers */
  HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency);
  
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK)
  {
    
    
    Error_Handler();
  }
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
    
    
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_RTC_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  printf("\r\n********    STM32F13c6t6 LowPower Test  *******\r\n");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    printf("Press WAKEUP button to enter STOP modes \r\n\r\n");

    printf("STOPpMode!\r\nPress WAKE_UP button to wake up ...\r\n");
    
 
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
		SYSCLKConfig_STOP();
    MX_USART1_UART_Init();
    printf("\r\nSTOP_MODE wake up,system running continue ... \r\n");
}
  /* USER CODE END 3 */
}

实验结果

程序开始,进入STOP_MODE低功耗模式,运行结果如下
在这里插入图片描述

STANDBY_MODE模式

待机模式:此时内核停止,外设也停止工作,1.2V域断电,SRAM和寄存器内容将丢失。待机模式唤醒后是重新运行程序,相当于重启,而不是在程序原来的位置继续运行。待机模式只能从WAKEUP引脚上升沿或下降沿,RTC,复位引脚,IWDG(独立看门狗) 复位唤醒。不能通过其他中断唤醒。前面睡眠模式和停止模式可以通过WAKEUP引脚的外部中断唤醒,但是待机模式不能通过外部中断唤醒。

实验过程以后再添加

总结

本章介绍了STM32的几种低功耗模式,这个在实际项目中用的非常多,特别是STOP_MODE和SLEEP_MODE

猜你喜欢

转载自blog.csdn.net/bin_zhang1/article/details/128852895