定时器是每个MCU都拥有的外设之一,某些MCU的定时器功能非常强大,例如提供PWM、输入捕获等功能。然而,定时器最基本的功能是执行周期性处理,可以通过定时器来完成这种任务。
由于成本问题,不同MCU自带的硬件定时器数量不同。FreeRTOS也提供了定时器功能,但它是软件定时器,相对硬件定时器来说,精度会降低,但对于普通的周期性处理任务来说足够了。当MCU硬件定时器数量不够时,则可以考虑使用FreeRTOS的软件定时器。
软件定时器允许设置一个时间,当设定的时间到达时,就会执行指定的功能函数,称为定时器回调函数。定时器的定时周期即是回调函数执行的两次间隔。回调函数在定时器服务任务中执行,所以绝不能在回调函数中调用会阻塞任务的API函数,如vTaskDelay()、vTaskDelayUnti(),以及一些访问队列和信号量的非零阻塞时间的API函数等。
定时器服务任务是由FreeRTOS提供的一个可选的、不属于内核的功能。这个任务提供定时器功能。FreeRTOS提供了许多和定时器相关的API函数,这些API函数大多是通过队列发送命令给定时器服务任务。这个队列被称为定时器命令队列,是提供给FreeRTOS的软件定时器使用的,用户不能直接访问。
![image-20240111193709360](https://lxlinux.superbed.verylink.top/item/659fd346871b83018a883b15.png)
左侧部分属于用户应用程序的一部分,并且会在某个用户创建的用户任务中调用。图中右侧部分是定时器服务任务的任务函数,定时器命令队列将用户应用任务和定时器服务任务连接在一起。在这个例子中,应用程序调用了函数 xTimerReset(),结果就是复位命令会被发送到定时器命令队列中,定时器服务任务会处理这个命令。应用程序是通过函数 xTimerReset()间接的向定时器命令队列发送了复位命令,并不是直接调用类似 xQueueSend()这样的队列操作函数发送的。
定时器相关配置
配置在文件 FreeRTOSConfig.h 中。
1、configUSE_TIMERS
如果要使用软件定时器的话宏 configUSE_TIMERS 一定要设置为 1,当设置为 1 的话定时器服务任务就会在启动 FreeRTOS 调度器的时候自动创建。
2、configTIMER_TASK_PRIORITY
设置软件定时器服务任务的任务优先级,可以为 0~( configMAX_PRIORITIES-1)。优先级一定要根据实际的应用要求来设置。如果定时器服务任务的优先级设置的高的话,定时器命令队列中的命令和定时器回调函数就会及时的得到处理。
3、configTIMER_QUEUE_LENGTH
此宏用来设置定时器命令队列的队列长度。
4、configTIMER_TASK_STACK_DEPTH
此宏用来设置定时器服务任务的任务堆栈大小,单位为字,不是字节!,对于 STM32 来说一个字是 4 字节。由于定时器服务任务中会执行定时器的回调函数,因此任务堆栈的大小一定要根据定时器的回调函数来设置。
单次定时器和周期定时器
软件定时器分两种:单次定时器和周期定时器,单次定时器的话定时器回调函数就执行一次,比如定时 1s,当定时时间到了以后就会执行一次回调函数,然后定时器就会停止运行。对于单次定时器我们可以再次手动重新启动(调用相应的 API 函数即可),但是单次定时器不能自动重启。相反的,周期定时器一旦启动以后就会在执行完回调函数以后自动的重新启动,这样回调函数就会周期性的执行。
![image-20240111193712785](https://lxlinux.superbed.verylink.top/item/659fd346871b83018a883b0f.png)
Timer1 为单次定时器,定时器周期为 100,Timer2 为周期定时器,定时器周期为 200。
API
1、复位软件定时器
有时候我们可能会在定时器正在运行的时候需要复位软件定时器,复位软件定时器的话会重新计算定时周期到达的时间点,这个新的时间点是相对于复位定时器的那个时刻计算的,并不是第一次启动软件定时器的那个时间点。下图演示了这个过程,Timer1 是单次定时器,定时周期是 5s:
![image-20240111193717057](https://tuchuang-lxq.oss-cn-qingdao.aliyuncs.com/image-20240111193717057.png)
定时器复位过程,这是一个通过按键打开 LCD 背光的例子,我们假定当唤醒键被按下的时候应用程序打开 LCD 背光,当 LCD 背光点亮以后如果 5s 之内唤醒键没有再次按下就自动熄灭。如果在这 5s 之内唤醒键被按下了,LCD 背光就从按下的这个时刻起再亮 5s。
FreeRTOS 提供了两个 API 函数来完成软件定时器的复位:
![image-20240111193720867](https://lxlinux.superbed.verylink.top/item/659fd35f871b83018a889d44.png)
2、创建软件定时器
![image-20240111193724515](https://lxlinux.superbed.verylink.top/item/659fd353871b83018a8871ea.png)
3、开启软件定时器
如果软件定时器停止运行的话可以使用 FreeRTOS 提供的两个开启函数来重新启动软件定时器。
![image-20240111193727021](https://lxlinux.superbed.verylink.top/item/659fd34c871b83018a885323.png)
4、停止软件定时器
![image-20240111193729321](https://lxlinux.superbed.verylink.top/item/659fd346871b83018a883b14.png)
具体的函数使用大家可以在用到的时候搜索用法,看一遍其实也记不住的。
FreeRTOS系列42
FreeRTOS系列 · 目录
上一篇FreeRTOS内核时钟不对的问题解决下一篇CMSIS-RTOS相关的一些内容
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !