FreeRTOS 低功耗之待机模式

本文详细介绍了STM32F103和STM32F4xx系列微控制器如何进入及退出待机模式的方法,并提供了注意事项。对于STM32F103,可通过调用PWR_EnterSTANDBYMode函数进入待机模式;对于STM32F4xx,同样通过该函数实现。从待机模式唤醒的方式包括外部复位、WKUP引脚、RTC闹钟事件等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STM32F103 如何进入待机模式
在 FreeRTOS 系统中,让 STM32 进入待机模式比较容易,调用固件库函数PWR_EnterSTANDBYMode 即可。 
STM32F103 如何退出待机模式
让 STM32 从待机模式唤醒可以通过外部复位(NRST 引脚)、 IWDG 复位、 WKUP 引脚上的上升沿或
RTC 闹钟事件的上升沿。从待机唤醒后,除了电源控制/状寄存器,所有寄存器被复位。
从待机模式唤醒后的代码执行等同于复位后的执行。电源控制/状态寄存器(PWR_CSR)将会指示内核
由待机状态退出。
在开发板上面是通过 K2 按键来唤醒,K2 按键使用的引脚就是 WKUP 引脚。
STM32F103 使用待机模式注意事项
待机模式要注意以下问题:
在待机模式下,所有的 I/O 引脚处于高阻态,除了以下的引脚:
复位引脚(始终有效)。
当被设置为防侵入或校准输出时的 TAMPER 引脚。
被使能的唤醒引脚。

STM32F4xx 如何进入待机模式
在 FreeRTOS 系统中,让 STM32 进入待机模式比较容易,调用固件库函数
PWR_EnterSTANDBYMode 即可。
STM32F4xx 如何退出待机模式
让 STM32 从待机模式唤醒可以通过外 WKUP 引脚上升沿、 RTC 闹钟(闹钟 A 和闹钟 B)、 RTC 唤
醒事件、 RTC 入侵事件、 RTC 时间戳事件、 NRST 引脚外部复位和 IWDG 复位,唤醒后除了电源控制/
状寄存器,所有寄存器被复位。
从待机模式唤醒后的代码执行等同于复位后的执行。电源控制/状态寄存器(PWR_CSR)将会指示内核
由待机状态退出。
早期工程版本是通过 K2 按键,即引脚 PC13 检测 RTC 的入侵事件进行唤醒,实际测试发现问题较多。
本实验将其改为复位按键进行唤醒,可以这么做是因为系统进入到待机模式后,被唤醒后系统的执行过程
等同于进行复位。

STM32F4xx 使用待机模式注意事项
待机模式要注意以下问题:
将选择的待机模式唤醒源(RTC 闹钟 A、 RTC 闹钟 B、 RTC 唤醒、 RTC 入侵或 RTC 时间戳标志)对
应的 RTC 标志清零,防止无法正常进入待机模式。
待机模式下的 I/O 状态
复位引脚(仍可用)。
RTC_AF1 引脚 (PC13)(如果针对入侵、时间戳、 RTC 闹钟输出或 RTC 时钟校准输出进行了配置)。
WKUP 引脚 (PA0)(如果使能)。

### FreeRTOS 实现低功耗模式配置方法 #### 1. 配置 `FreeRTOSConfig.h` 为了使能并配置 FreeRTOS 的 Tickless 模式,在 `FreeRTOSConfig.h` 文件中需设置特定宏定义。 - **使能启用 Tickless 模式** 定义 `configUSE_TICKLESS_IDLE` 宏为 1 来开启此功能。这允许系统在空闲时停止计数器中断,从而减少能耗[^1]。 ```c #define configUSE_TICKLESS_IDLE 1 ``` - **配置进入低功耗模式的时间** 设置 `configEXPECTED_IDLE_TIME_BEFORE_SLEEP` 宏来指定预计的空闲时间长度。如果预测到即将有一段时间不会有任何任务运行,则可以安全地进入更深的休眠状态。 ```c #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP ( ticktype_t )50 / portTICK_PERIOD_MS; ``` #### 2. 进入 Tickless 模式的条件 当所有可执行的任务都处于阻塞或挂起状态下,并且满足预设的空闲周期阈值时,FreeRTOS 将准备进入低功耗模式。此时会调用钩子函数 `vApplicationTickHook()` 或者直接跳转至 `vPortSuppressTicksAndSleep()` 函数处理具体的节能操作。 #### 3. 执行低功耗的具体过程 ##### 3.1 使用 `vPortSuppressTicksAndSleep()` 该函数负责暂停滴答定时器(即关闭定期产生的硬件中断),并通过 WFI/WFE 指令让 CPU 进入等待事件/中断的状态,直到下一个外部触发唤醒为止[^4]。 ```c void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { /* 关闭滴答中断 */ /* 调整电源管理模式 */ /* 发送CPU进入待机命令 */ } ``` ##### 3.2 自定义低功耗函数 `MySleep()` 对于某些应用场景可能需要更精细控制电源行为的情况,可以在项目里编写自己的睡眠逻辑作为替代方案: ```c static void prvSetupTimerForRunTimeStats(void); extern uint32_t ulLowPowerTickCount; void MySleep(TickType_t expected_idle_time) { /* 用户自定义前处理动作 */ /* 停止滴答中断源 */ prvStopTimer(); /* 计算预期休眠时长 */ ulLowPowerTickCount += expected_idle_time; /* ARM 架构下使用WFI指令 */ __asm volatile ("wfi"); /* 用户自定义后恢复动作 */ } /* 替换默认实现 */ #define vPortSuppressTicksAndSleep(x) MySleep((x)) ``` 上述代码展示了如何创建一个名为 `MySleep` 的新函数用于代替标准库中的 `vPortSuppressTicksAndSleep` 。这样做可以让开发者根据具体需求调整系统的响应方式和性能表现[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值