一、软件定时器简介
软件定时器允许设置一段时间,当设置的时间到达之后就执行指定的功能,执行功能的函数称为回调函数。相比于硬件定时器,软件定时器精度能差点(因为优先级低容易被打断)但是却不像硬件定时器那样资源有限。
软件定时器的回调函数是在定时器服务任务中执行的,所以不能在回调函数中调用任何会阻塞任务的 API 函数!比如 vTaskDelay()、 vTaskDelayUnti(),还有一些访问队列或者信号量的非零阻塞时间的 API 函数也不能调用。
二、定时器服务任务
FreeRTOS 提供了很多定时器相关API函数,这些函数通过队列将数据发送到定时器服务任务中,再由定时器服务任务来读取这些命令,这个队列就叫做命令队列。定时器命令队列操作如下图:应用程序是通过函数 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 字节。由于定时器服务任务中会执行定时器的回调函数,因此任务堆栈的大小一定要根据定时器的回调函数来设置。
四、单次定时器和周期定时器
两个的区别其实就是一个只调用一次回调函数,另一个重复调用回调函数。重复调用的方法其实就是自动重启。单次定时器也可以重启,只不过需要手动重启。
五、定时器相关API函数
1、软件定时器复位
函数 | 描述 |
xTimerReset() | 复位软件定时器,用在任务中 |
xTimerResetFromISR() | 复位软件定时器,用在中断服务函数中 |
函数xTimerReset():
BaseType_t xTimerReset( TimerHandle_t xTimer,
TickType_t xTicksToWait )
参数:xTimer:要复位的软件定时器的句柄;
xTicksToWait:设置阻塞时间。
返回值: pdPASS: 命令发送成功;
pdFAIL: 命令发送失败。
2、创建软件定时器
函数 | 描述 |
xTimerCreate() | 使用动态方法创建软件定时器 |
xTimerCreateStatic() | 使用静态方法创建软件定时器 |
函数xTimerCreate():
TimerHandle_t xTimerCreate( const char * const pcTimerName,
TickType_t xTimerPeriodInTicks,
UBaseType_t uxAutoReload,
void * pvTimerID,
TimerCallbackFunction_t pxCallbackFunction )
新创建的软件定时器处于休眠状态。
参数:pcTimerName:软件定时器名字,名字是一串字符串,用于调试使用;
xTimerPeriodInTicks :软件定时器的定时器周期,单位是时钟节拍数。可以借助portTICK_PERIOD_MS 将 ms 单位转换为时钟节拍数。例如:定时器的周期为 100 个时钟节拍的话,那么 xTimerPeriodInTicks 就为 100,当定时器周期为 500ms 的时候 xTimerPeriodInTicks 就可以设置为(500/ portTICK_PERIOD_MS);
uxAutoReload:设置定时器模式。pdTRUE 表示创建的是周期定时器;pdFALSE 表示创建的是单次定时器;
pvTimerID:定时器 ID 号,一般情况下每个定时器都有一个回调函数,当定时器定时周期到了以后就会执行这个回调函数。但是 FreeRTOS 也支持多个 定时器共用同一个回调函数,在回调函数中根据定时器的 ID 号来处理不同的定时器;
pxCallbackFunction:定时器回调函数,当定时器定时周期到了以后就会调用这个函数。
返回值:NULL: 软件定时器创建失败;其他值: 创建成功的软件定时器句柄。
3、开启软件定时器
函数 | 描述 |
xTimerStart() | 开启软件定时器,用于任务中 |
xTimerStartFromISR() | 开启软件定时器,用于中断中 |
函数 xTimerStart():
BaseType_t xTimerStart( TimerHandle_t xTimer,
TickType_t xTicksToWait )
如果软件定时器没有运行的话调用函数 xTimerStart()就会计算定时器到期时间,如果软件定时器正在运行的话调用函数 xTimerStart()的结果和 xTimerReset()一样。
参数:xTimer:要开启的软件定时器的句柄;
xTicksToWait: 设置阻塞时间。
返回值:pdPASS: 命令发送成功;pdFAIL: 命令发送失败。
4、停止软件定时器
函数 | 描述 |
xTimerStop() | 停止软件定时器,用于任务中 |
xTimerStopFromISR() | 停止软件定时器,用于中断服务函数中 |
函数 xTimerStop():
BaseType_t xTimerStop ( TimerHandle_t xTimer,
TickType_t xTicksToWait )
参数:xTimer:要停止的软件定时器的句柄;
xTicksToWait:设置阻塞时间。
返回值:pdPASS: 命令发送成功;pdFAIL: 命令发送失败。