二十三、软件定时器

文章目录

  • 1、FreeRTOS中的软件定时器
  • 2、什么是守护任务
  • 3、软件定时器回调函数
  • 4、相关的API函数
    • (1)创建定时器——xTimerCreate
    • (2)删除定时器——xTimerDelete
    • (3)启动定时器——xTimerStart
    • (4)停止定时器——xTimerStop
    • (5)复位定时器——xTimerReset
    • (6)修改定时器周期——xTimerChangePeriod
    • (7)定时器ID相关函数

1、FreeRTOS中的软件定时器

在FreeRTOS中使用RTOS守护任务来处理软件定时器(即执行定时器函数),而其他的操作系统中都是在硬件滴答定时器(tick)中进行软件定时器的处理,相比之下FreeRTOS处理软件定时器的效率较低。

即FreeRTOS中软件定时器的执行/处理不是在tick中断中执行的,而是在RTOS Damemon Task这个RTOS 守护任务中执行。

当 FreeRTOS 的配置项 configUSE_TIMERS 被设置为 1 时,在启动调度器时,会自动创建 RTOS Damemon Task。

所以我们自定义的任务函数如果要想使用软件定时器,都是通过“定时器命令队列”来和守护任务进行交互的。
二十三、软件定时器_第1张图片

2、什么是守护任务

守护任务主要执行的工作:
1)处理命令:从命令队列里取出命令、处理
2)执行定时器的回调函数

守护任务的 优先级为: configTIMER_TASK_PRIORITY 。
定时器命令队列的长度为configTIMER_QUEUE_LENGTH。

3、软件定时器回调函数

void ATimerCallback( TimerHandle_t xTimer );

定时器的回调函数是在守护任务中被调用的,守护任务不是专为某个定时器服务的,它还要处理其他定时器。

所以这就要求其回调函数快进快出,不能进入阻塞状态,即这个回调函数一定不能阻塞。

4、相关的API函数

记住前面说到的FreeRTOS对应定时器的所有操作都是经过Timer command queue这个队列来进行中继命令的,

(1)创建定时器——xTimerCreate

创建成功后会返回一个定时器句柄。

/* 使用动态分配内存的方法创建定时器
* pcTimerName:定时器名字, 用处不大, 就在调试时用到
* xTimerPeriodInTicks: 周期, 以 Tick 为单位
* uxAutoReload: 类型, pdTRUE 表示自动加载, pdFALSE 表示一次性
* pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器
* pxCallbackFunction: 回调函数
* 返回值: 成功则返回 TimerHandle_t, 否则返回 NULL
*/
TimerHandle_t xTimerCreate( const char * const pcTimerName,
							const TickType_t xTimerPeriodInTicks,
							const UBaseType_t uxAutoReload,
							void * const pvTimerID,
							TimerCallbackFunction_t pxCallbackFunction );
/* 使用静态分配内存的方法创建定时器
* pcTimerName:定时器名字, 用处不大, 尽在调试时用到
* xTimerPeriodInTicks: 周期, 以 Tick 为单位
* uxAutoReload: 类型, pdTRUE 表示自动加载, pdFALSE 表示一次性
* pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器
* pxCallbackFunction: 回调函数
* pxTimerBuffer: 传入一个 StaticTimer_t 结构体, 将在上面构造定时器
* 返回值: 成功则返回 TimerHandle_t, 否则返回 NULL
*/
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
 								 TickType_t xTimerPeriodInTicks, UBaseType_t uxAutoReload,
 								 void * pvTimerID,
 							 	 TimerCallbackFunction_t pxCallbackFunction,
 								 StaticTimer_t *pxTimerBuffer );

(2)删除定时器——xTimerDelete

/* 删除定时器
* xTimer: 要删除哪个定时器
* xTicksToWait: 超时时间
* 返回值: pdFAIL 表示"删除命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );

(3)启动定时器——xTimerStart

/* 启动定时器
* xTimer: 哪个定时器
* xTicksToWait: 超时时间
* 返回值: pdFAIL 表示"启动命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
/* 启动定时器(ISR 版本)
* xTimer: 哪个定时器
* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,
* 如果守护任务的优先级比当前任务的高,
* 则"*pxHigherPriorityTaskWoken = pdTRUE",
* 表示需要进行任务调度
* 返回值: pdFAIL 表示"启动命令"无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken );

(4)停止定时器——xTimerStop

/* 停止定时器
* xTimer: 哪个定时器
* xTicksToWait: 超时时间
* 返回值: pdFAIL 表示"停止命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );
/* 停止定时器(ISR 版本)
* xTimer: 哪个定时器
* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,
* 如果守护任务的优先级比当前任务的高,
* 则"*pxHigherPriorityTaskWoken = pdTRUE",
* 表示需要进行任务调度
* 返回值: pdFAIL 表示"停止命令"无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerStopFromISR( TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken );

(5)复位定时器——xTimerReset

 /* 复位定时器
 xTimer: 哪个定时器
* xTicksToWait: 超时时间
* 返回值: pdFAIL 表示"复位命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
/* 复位定时器(ISR 版本)
* xTimer: 哪个定时器
* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,
* 如果守护任务的优先级比当前任务的高,
* 则"*pxHigherPriorityTaskWoken = pdTRUE",
* 表示需要进行任务调度
* 返回值: pdFAIL 表示"停止命令"无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerResetFromISR( TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken );

(6)修改定时器周期——xTimerChangePeriod

/* 修改定时器的周期
* xTimer: 哪个定时器
* xNewPeriod: 新周期
* xTicksToWait: 超时时间, 命令写入队列的超时时间
* 返回值: pdFAIL 表示"修改周期命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, TickType_t xNewPeriod,TickType_t xTicksToWait );
/* 修改定时器的周期
* xTimer: 哪个定时器
* xNewPeriod: 新周期
* pxHigherPriorityTaskWoken: 向队列发出命令使得守护任务被唤醒,
* 如果守护任务的优先级比当前任务的高,
* 则"*pxHigherPriorityTaskWoken = pdTRUE",
* 表示需要进行任务调度
* 返回值: pdFAIL 表示"修改周期命令"在 xTicksToWait 个 Tick 内无法写入队列
* pdPASS 表示成功
*/
BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer,TickType_t xNewPeriod, BaseType_t *pxHigherPriorityTaskWoken );

(7)定时器ID相关函数

在定时器结构体里面有一个ID号
二十三、软件定时器_第2张图片

这个定时器ID可以用来标记定时器,表示自己是什么定时器,可以用来保存参数,给回调函数使用。

/* 获得定时器的 ID
* xTimer: 哪个定时器
* 返回值: 定时器的 ID
*/
void *pvTimerGetTimerID( TimerHandle_t xTimer );
/* 设置定时器的 ID
* xTimer: 哪个定时器
* pvNewID: 新 ID
* 返回值: 无
*/
void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );

你可能感兴趣的:(FreeRTOS,iot)