STM32CubeMX学习笔记(16)——电源管理(PWR)低功耗停止模式

发布者:EnchantedDream最新更新时间:2025-02-19 来源: jianshu关键字:STM32CubeMX  电源管理  PWR  低功耗  停止模式 手机看文章 扫描二维码
随时随地手机看文章

    // 重新配置时钟源后始终状态

    printf('rn 重新配置后的时钟状态:rn');

    printf(' SYSCLK 频率:%d,rn HCLK 频率:%d,rn PCLK1 频率:%d,rn PCLK2 频率:%d,rn 时钟源:%d (0 表示 HSI,8 表示 PLLCLK)n',SYSCLK_Frequency,HCLK_Frequency,PCLK1_Frequency,PCLK2_Frequency,SYSCLK_Source);

    HAL_Delay(2000);

    HAL_GPIO_WritePin(GPIOB, LED_B_Pin, GPIO_PIN_SET);

    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

}



3.2 RTC时钟唤醒

3.2.1 添加RTC时钟

查看 STM32CubeMX学习笔记(14)——RTC实时时钟使用

3.1.2 添加LED灯

添加绿灯 PB0 表示运行状态,红灯 PB5 表示睡眠状态,蓝灯 PB1 表示刚从睡眠状态中被唤醒。
查看 STM32CubeMX学习笔记(2)——GPIO接口使用

3.1.3 添加串口打印

添加 USART1 用于打印信息。
查看 STM32CubeMX学习笔记(6)——USART串口使用

3.2.4 使能RTC闹钟中断

3.2.5 生成代码

输入项目名和项目路径


选择应用的 IDE 开发环境 MDK-ARM V5


每个外设生成独立的 ’.c/.h’ 文件
不勾:所有初始化代码都生成在 main.c
勾选:初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。


点击 GENERATE CODE 生成代码


3.2.6 修改中断回调函数

打开 stm32f1xx_it.c 中断服务函数文件,找到 RTC 闹钟中断的服务函数 RTC_Alarm_IRQHandler()
中断服务函数里面就调用了 RTC 闹钟中断处理函数 HAL_RTC_AlarmIRQHandler()


打开 stm32f1xx_hal_rtc.c 文件,找到RTC闹钟中断处理函数原型 HAL_RTC_AlarmIRQHandler(),其主要作用就是判断是否RTC中断,清除中断标识位,然后调用中断回调函数 HAL_RTC_AlarmAEventCallback()。


/* NOTE: This function Should not be modified, when the callback is needed,
theHAL_RTC_AlarmAEventCallback could be implemented in the user file
*/
这个函数不应该被改变,如果需要使用回调函数,请重新在用户文件中实现该函数。

HAL_RTC_AlarmAEventCallback() 按照官方提示我们应该再次定义该函数,__weak 是一个弱化标识,带有这个的函数就是一个弱化函数,就是你可以在其他地方写一个名称和参数都一模一样的函数,编译器就会忽略这一个函数,而去执行你写的那个函数;而 UNUSED(hrtc) ,这就是一个防报错的定义,当传进来的RTC号没有做任何处理的时候,编译器也不会报出警告。其实我们在开发的时候已经不需要去理会中断服务函数了,只需要找到这个中断回调函数并将其重写即可而这个回调函数还有一点非常便利的地方这里没有体现出来,就是当同时有多个中断使能的时候,STM32CubeMX会自动地将几个中断的服务函数规整到一起并调用一个回调函数,也就是无论几个中断,我们只需要重写一个回调函并判断传进来的端口号即可。


接下来我们就在 stm32f1xx_it.c 这个文件的最下面添加 HAL_RTC_AlarmAEventCallback()

/* USER CODE BEGIN 1 */

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)

{

    SystemClock_Config();  // STOP模式唤醒后默认时钟主频为内部8M时钟,所以要先初始化时钟配置

    // 亮蓝灯

    HAL_GPIO_WritePin(GPIOB, LED_B_Pin, GPIO_PIN_RESET);

    printf('3s时间到,唤醒!rn');

}

/* USER CODE END 1 */


3.2.7 添加RTC闹钟中断启动函数

void RTC_AlarmStart(void)

{

    RTC_AlarmTypeDef sAlarm = {0};

    RTC_TimeTypeDef tim = {0};


    // 获取当前时间

    HAL_RTC_GetTime(&hrtc, &tim, RTC_FORMAT_BIN);


    sAlarm.AlarmTime.Hours = tim.Hours;

    sAlarm.AlarmTime.Minutes = tim.Minutes;

    sAlarm.AlarmTime.Seconds = tim.Seconds + 3;  /* 设置下次闹钟提醒时间是当前时间的3s之后 */

    sAlarm.Alarm = RTC_ALARM_A;


    // 启动闹钟中断事件

    HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);

}


3.2.8 修改main函数

初始化完成后使用 LED 及串口表示运行状态,LED 灯为绿色时表示正常运行,红灯时表示停止状态,蓝灯时表示刚从停止状态中被唤醒。在停止模式下,I/O 口会保持停止前的状态,所以 LED 彩灯在停止模式时也会保持亮红灯。

程序执行一段时间后,调用库函数 HAL_PWR_EnterSTOPMode 把调压器设置在低功耗模式,进入停止状态。由于 WFI 停止模式可以使用任意 EXTI 的中断唤醒,所以我们可以使用RTC闹钟中断唤醒。

当系统进入停止状态后,隔 3 秒后闹钟唤醒系统,当执行完中断服务函数后,会继续执行 HAL_PWR_EnterSTOPMode 函数后的代码。


/**

  * @brief  The application entry point.

  * @retval int

  */

int main(void)

{

  /* USER CODE BEGIN 1 */

  uint32_t SYSCLK_Frequency = 0;

  uint32_t HCLK_Frequency = 0;

  uint32_t PCLK1_Frequency = 0;

  uint32_t PCLK2_Frequency = 0;

  uint32_t SYSCLK_Source = 0;

  /* 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_USART1_UART_Init();

  /* USER CODE BEGIN 2 */

  printf('stop mode testrn');

  /* USER CODE BEGIN 2 */

  

  /* USER CODE END 2 */


  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

    // 使用绿灯指示,运行状态

    HAL_GPIO_WritePin(GPIOB, LED_G_Pin, GPIO_PIN_RESET);

    HAL_Delay(2000);

    HAL_GPIO_WritePin(GPIOB, LED_G_Pin, GPIO_PIN_SET);

    // 任务执行完毕,进入睡眠降低功耗


    // 使用红灯指示,进入停止状态

    HAL_GPIO_WritePin(GPIOB, LED_R_Pin, GPIO_PIN_RESET);

    // 暂停滴答时钟,防止通过滴答时钟中断唤醒

    HAL_SuspendTick();

    // 配置下次唤醒的闹钟时间

    RTC_AlarmStart();

    // 使能PWR时钟

    __HAL_RCC_PWR_CLK_ENABLE();

    // 清除唤醒标记

    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

    // 进入停止模式

    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);


    HAL_GPIO_WritePin(GPIOB, LED_R_Pin, GPIO_PIN_SET);

    // 被唤醒后,恢复滴答时钟

    HAL_ResumeTick();

    // 获取重新配置后的时钟状态

    SYSCLK_Frequency = HAL_RCC_GetSysClockFreq();

    HCLK_Frequency = HAL_RCC_GetHCLKFreq();

    PCLK1_Frequency = HAL_RCC_GetPCLK1Freq();

    PCLK2_Frequency = HAL_RCC_GetPCLK2Freq();

    SYSCLK_Source = __HAL_RCC_GET_SYSCLK_SOURCE();

  

    // 重新配置时钟源后始终状态

    printf('rn 重新配置后的时钟状态:rn');

    printf(' SYSCLK 频率:%d,rn HCLK 频率:%d,rn PCLK1 频率:%d,rn PCLK2 频率:%d,rn 时钟源:%d (0 表示 HSI,8 表示 PLLCLK)n',SYSCLK_Frequency,HCLK_Frequency,PCLK1_Frequency,PCLK2_Frequency,SYSCLK_Source);

    HAL_Delay(2000);

    HAL_GPIO_WritePin(GPIOB, LED_B_Pin, GPIO_PIN_SET);

    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

}


四、注意事项

用户代码要加在 USER CODE BEGIN N 和 USER CODE END N 之间,否则下次使用 STM32CubeMX 重新生成代码后,会被删除。

进入低功耗之前可以将引脚全部配置为浮空输入或者Anglog模式,这样最省电,如果你是用STM32CUBEMX,在这里可以看到这么一项配置就是将没有用到的引脚配置为了Anglog模式:

当系统处于睡眠模式低功耗状态时(包括后面讲解的停止模式及待机模式),使用 DAP 下载器是无法给芯片下载程序的,所以下载程序时要先把系统唤醒。或者使用如下方法:按着板子的复位按键,使系统处于复位状态,然后点击电脑端的下载按钮下载程序,这时再释放复位按键,就能正常给板子下载程序了。

[1] [2]
关键字:STM32CubeMX  电源管理  PWR  低功耗  停止模式 引用地址:STM32CubeMX学习笔记(16)——电源管理(PWR)低功耗停止模式

上一篇:STM32CubeMX学习笔记(17)——电源管理(PWR)低功耗待机模式
下一篇:STM32CubeMX学习笔记(15)——电源管理(PWR)低功耗睡眠模式

小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved