FreeRTOS之软件定时器详解
内容提要
定时器是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软件定时器复位时,新的定时周期从什么时刻开始计算?
复位软件定时器会重新计算定时周期到达的时间点,这个新时间点是相对于复位定时器的那个时刻计算的,而不是第一次启动软件定时器的那个时间点。