FreeRTOS之软件定时器详解

💡 原文中文,约2300字,阅读约需6分钟。
📝

内容提要

定时器是MCU的外设之一,可以执行周期性处理任务。FreeRTOS提供了软件定时器功能,精度较硬件定时器低,但足够普通任务使用。定时器服务任务处理定时器命令队列中的命令。配置需在FreeRTOSConfig.h中设置。软件定时器分为单次和周期定时器,单次定时器执行一次回调函数后停止,周期定时器会自动重启。可通过API函数复位、创建、开启和停止软件定时器。

🔎

延伸解读

回调函数的执行限制

文章明确指出,定时器回调函数在定时器服务任务中执行,因此绝不能调用会阻塞任务的API函数,如vTaskDelay()、vTaskDelayUnti(),以及访问队列和信号量时使用非零阻塞时间的API。这意味着在回调函数中应避免任何可能导致任务挂起的操作,否则会阻塞定时器服务任务,影响其他定时器的处理。

定时器服务任务的配置要点

使用软件定时器需在FreeRTOSConfig.h中设置configUSE_TIMERS为1,调度器启动时会自动创建定时器服务任务。其优先级configTIMER_TASK_PRIORITY应根据实际应用设置,优先级高则命令和回调处理更及时。队列长度configTIMER_QUEUE_LENGTH和任务堆栈深度configTIMER_TASK_STACK_DEPTH也需合理配置,堆栈大小以字为单位(STM32中1字为4字节),且需根据回调函数的需求来设定。

复位定时器的实际应用

复位软件定时器会重新计算定时周期到达的时间点,新时间点从复位时刻算起,而非首次启动时刻。文章以按键唤醒LCD背光为例:点亮后5秒内若再次按键,则从按键时刻重新计时5秒。这适用于需要“超时重置”的场景,FreeRTOS提供了两个API函数用于复位,但文章未列出具体函数名,需查阅相关文档。

❓

Q&A

FreeRTOS软件定时器的精度和硬件定时器相比如何?

FreeRTOS软件定时器的精度低于硬件定时器,但对于普通的周期性处理任务来说足够了。当MCU硬件定时器数量不够时,可以考虑使用软件定时器。

FreeRTOS软件定时器的回调函数为什么不能调用阻塞API函数?

因为定时器回调函数在定时器服务任务中执行,如果调用阻塞API函数(如vTaskDelay()、vTaskDelayUntil(),以及一些访问队列和信号量的非零阻塞时间的API函数等),会阻塞定时器服务任务,影响其他定时器命令的处理。

FreeRTOS的定时器服务任务是如何与用户应用程序交互的?

用户应用程序通过调用定时器API函数(如xTimerReset())间接向定时器命令队列发送命令,定时器服务任务从队列中取出命令并处理。定时器命令队列是FreeRTOS软件定时器专用的,用户不能直接访问。

配置FreeRTOS软件定时器需要在FreeRTOSConfig.h中设置哪些宏?

需要设置:configUSE_TIMERS(设置为1以启用软件定时器,调度器启动时自动创建定时器服务任务)、configTIMER_TASK_PRIORITY(定时器服务任务优先级)、configTIMER_QUEUE_LENGTH(定时器命令队列长度)、configTIMER_TASK_STACK_DEPTH(定时器服务任务堆栈大小,单位为字)。

FreeRTOS的单次定时器和周期定时器有什么区别?

单次定时器在定时时间到达后执行一次回调函数然后停止运行,不能自动重启,但可以手动重新启动;周期定时器在每次执行完回调函数后自动重新启动,从而周期性地执行回调函数。

FreeRTOS软件定时器复位时,新的定时周期从什么时刻开始计算?

复位软件定时器会重新计算定时周期到达的时间点,这个新时间点是相对于复位定时器的那个时刻计算的,而不是第一次启动软件定时器的那个时间点。

🏷️

标签

➡️

继续阅读