欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

stm32的低功耗模式

程序员文章站 2022-07-02 09:48:31
...

本文以smt32L4R5ZIT6单片机为例,编写代码。本文只讲代码,不说废话。

单片机进入低功耗前,都应该关闭中断。同时在低功耗前加上如下代码功耗更低


  __HAL_RCC_PWR_CLK_ENABLE();//使能电源时钟
  HAL_PWR_EnableBkUpAccess();//使能LSE/RTC控制的备份域
  LSE_OFF_Config();//关闭LSE时钟,确保RTC关闭
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);//配置内部调节器输出电压(默认为Range1)
  __HAL_RCC_PWR_CLK_DISABLE();//关闭电源时钟

在进入低功耗前,都要求设置GPIO为模拟输入模式,代码如下

void GPIO_AnalogState_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOF_CLK_ENABLE();
    __HAL_RCC_GPIOG_CLK_ENABLE();
    __HAL_RCC_GPIOH_CLK_ENABLE();    
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Pin = GPIO_PIN_All;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);  
    __HAL_RCC_GPIOA_CLK_DISABLE();
    __HAL_RCC_GPIOB_CLK_DISABLE();
    __HAL_RCC_GPIOC_CLK_DISABLE();
    __HAL_RCC_GPIOD_CLK_DISABLE();
    __HAL_RCC_GPIOE_CLK_DISABLE();
    __HAL_RCC_GPIOF_CLK_DISABLE();
    __HAL_RCC_GPIOG_CLK_DISABLE();
    __HAL_RCC_GPIOH_CLK_DISABLE();
}

void RTC_Config()函数

void RTC_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
  __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); 
  __HAL_RCC_RTC_ENABLE();
}

1关断模式SHUTDOWN

关断模式

void test_shutdown(void)
{
  GPIO_AnalogState_Config();//设置GPIO为模拟输入
  __HAL_RCC_PWR_CLK_ENABLE();//使能电源时钟
  HAL_PWREx_EnterSHUTDOWNMode();//进入shutdown模式
  
}

2待机模式standby

待机模式

void test_standby_rtc(void) 
{
  /* set RTC clock */
//说明:这里可以设置RTC时钟唤醒待机模式,但是本文未设置RTC中断,所以此处代码省略.如果想要唤醒,应该在此处开启rtc唤醒
  RTC_Config();//配置RTC,因为前文介绍低功耗前关闭RTC,此处相当于重新打开
  GPIO_AnalogState_Config();//设置GPIO为低功耗模式
  __HAL_RCC_PWR_CLK_ENABLE();//使能电源时钟
  HAL_PWR_EnterSTANDBYMode();//进入STANDBY模式
}

3待机模式+RTC

待机模式+RTC并保留sram2中数据

void test_standby_rtc_sram2(void)
 {
  /* set RTC clock */
  /*这里可以设置RTC唤醒待机模式,但本文未设置,所以此处代码省略*/
  MX_RTC_Init();//初始化RTC
   GPIO_AnalogState_Config();//设置GPIO低功耗模式
   __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);//清除电源标志
  __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);//清除RTC唤醒定时器标志
  __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();//清除睡眠外部中断唤醒标志
  __HAL_RTC_TIMESTAMP_CLEAR_FLAG(&hrtc, RTC_FLAG_TSF);
  __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
  __HAL_RCC_PWR_CLK_ENABLE();//使能电源时钟
  /* Request to enter STANDBY mode with SRAM2 active */
  HAL_PWREx_EnableSRAM2ContentRetention();//**待机模式中SRAM2备份域
//  HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);//此代码是设置RTC定时器唤醒中断,5秒唤醒.此处作为示例代码,暂不使用
  HAL_PWR_EnterSTANDBYMode();//进入待机模式
}

4停止模式stop2

停止模式2

void test_stop2(void)
{
  GPIO_AnalogState_Config();
  __HAL_RCC_PWR_CLK_ENABLE();
  HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);//进入停止模式2
}

5停止模式2+RTC

void test_stop2_rtc(void)
{
  GPIO_AnalogState_Config();
  MX_RTC_Init();//配置RTC
  /* Enable Power Clock */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
  /* Clear RTC Wake Up timer Flag */
  __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
  __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
  __HAL_RTC_TIMESTAMP_CLEAR_FLAG(&hrtc, RTC_FLAG_TSF);
  __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG();
  HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);//设置RTC定时器唤醒,定时5s
  HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);//进入停止2模式
  SystemClock_80MHz(); //RTC定时5秒后唤醒,必须重新配置时钟
}

6停止模式1

停止模式1

void test_stop1_mroff(void)
{
  GPIO_AnalogState_Config();
  __HAL_RCC_PWR_CLK_ENABLE();
  
  /*进入停止模式1,主调节器关,低功耗调节器开*/
  HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
}

7停止模式1+RTC

停止模式1+RTC

void test_stop1_mroff_rtc(void)
{
  /* set RTC clock */
  /*这里可以设置RTC时钟唤醒*/
  RTC_Config();//配置RTC
  GPIO_AnalogState_Config();
  __HAL_RCC_PWR_CLK_ENABLE();
  
  /* Enter STOP 1 mode (Main Regulator OFF and Low Power Regulator On) */
  HAL_PWREx_EnterSTOP1Mode(PWR_STOPENTRY_WFI);
}

8低功耗睡眠模式2MHz

lpsleep_2mhz

void SystemClock_2MHz(void)//配置运行时钟为2MHz
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  /* MSI is enabled after System reset, update MSI to 2Mhz (RCC_MSIRANGE_5) */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  
  /* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI; 
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}


void test_lpsleep_2mhz(void)//睡眠模式配置
{
  GPIO_AnalogState_Config();
  __HAL_FLASH_SLEEP_POWERDOWN_ENABLE(); //在睡眠模式下启用flash power down,如果在低功耗下不需要flash进入待机模式,需要屏蔽这行代码
  SystemClock_2MHz();//配置2MHz(MSI)单片机运行时钟频率
  HAL_SuspendTick();//暂停时间增量防止系统中断唤醒,否则Systick中断在1ms内会唤醒设备

  /* 关闭所有时钟使能*/
  RCC->AHB1SMENR = 0x0; 
  RCC->AHB2SMENR = 0x0;
  RCC->AHB3SMENR = 0x0;
  RCC->APB1SMENR1 = 0x0;
  RCC->APB1SMENR2 = 0x0; 
  RCC->APB2SMENR = 0x0;
  __HAL_RCC_PWR_CLK_ENABLE();
    
  /*进入睡眠模式,主调节器关闭*/
  HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
}

9运行模式2MHz

2MHz的运行模式

void SystemClock_2MHz(void)//配置运行时钟为2MHz
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  /* MSI is enabled after System reset, update MSI to 2Mhz (RCC_MSIRANGE_5) */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  
  /* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI; 
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}


void test_lprun_2mhz(void)//配置2MHz的低功耗运行模式
{
  GPIO_AnalogState_Config();
  SystemClock_2MHz();//配置系统时钟2 MHz (MSI) 
  HAL_SuspendTick();//暂停时间增量以防止系统中断唤醒。
  __HAL_RCC_LPUART1_CLK_DISABLE();//失能低功耗串口时钟
  __HAL_RCC_PWR_CLK_ENABLE();//开启电源时钟
  HAL_PWREx_EnableLowPowerRunMode();//低功耗运行模式2MHz
  __HAL_RCC_PWR_CLK_DISABLE();//失能电源时钟
}

10睡眠模式range2(24MHz)

void SystemClock_24MHz(void)//配置24MHz时钟
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  /* MSI is enabled after System reset, update MSI to 24Mhz (RCC_MSIRANGE_9) */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_9;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI; 
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

void test_sleep_range2_24mhz(void)//设置睡眠模式
{
  GPIO_AnalogState_Config();
  SystemClock_24MHz();//配置系统时钟24 MHz (MSI)
  __HAL_RCC_PWR_CLK_ENABLE();
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);//配置内部主调节器输出电压

  HAL_SuspendTick();//暂停Systick中断
  RCC->AHB1SMENR = 0x0; //关闭所有时钟使能
  RCC->AHB2SMENR = 0x0;
  RCC->AHB3SMENR = 0x0;
  RCC->APB1SMENR1 = 0x0;
  RCC->APB1SMENR2 = 0x0; 
  RCC->APB2SMENR = 0x0;
  HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);//进入睡眠模式,主调节器开
}

11睡眠模式range1(80MHz)

sleep_range1_80mhz

void SystemClock_80MHz(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  /* MSI is enabled after System reset, activate PLL with MSI as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 40;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLP = 7;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

void test_sleep_range1_80mhz(void)
{
  GPIO_AnalogState_Config();
  SystemClock_80MHz();//配置系统频率80 MHz (MSI)
  HAL_SuspendTick();
  RCC->AHB1SMENR = 0x0; 
  RCC->AHB2SMENR = 0x0;
  RCC->AHB3SMENR = 0x0;
  RCC->APB1SMENR1 = 0x0;
  RCC->APB1SMENR2 = 0x0; 
  RCC->APB2SMENR = 0x0;
  __HAL_RCC_PWR_CLK_ENABLE();
  HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);//睡眠模式主调节器开
}

12运行模式range2(24MHz)

void SystemClock_24MHz(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  /* MSI is enabled after System reset, update MSI to 24Mhz (RCC_MSIRANGE_9) */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_9;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI; 
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}


void test_run_range2_24mhz(void)
{
  SystemClock_24MHz();//设置系统时钟为24 MHz
  __HAL_RCC_PWR_CLK_ENABLE();
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);//设置内部主调节器输出电压
  __HAL_RCC_PWR_CLK_DISABLE();
  GPIO_AnalogState_Config();
  __HAL_RCC_LPUART1_CLK_DISABLE();//关闭低功耗串口
  HAL_SuspendTick();
}

13运行模式range1(80MHz)

void SystemClock_80MHz(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  /* MSI is enabled after System reset, activate PLL with MSI as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 40;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLP = 7;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

void test_run_range1_80mhz(void)
{
  GPIO_AnalogState_Config();
  __HAL_RCC_LPUART1_CLK_DISABLE();
  SystemClock_80MHz();//配置系统时钟80 MHz (MSI)
  HAL_SuspendTick();
}

至此,低功耗模式的代码呈现完毕。

相关标签: STM32开发