- 软件定时器分为单次和自动重载两种。
- xTimerCreate只创建,xTimerStart才启动。
- 所有回调都在公共Timer Service Task中执行。
- 回调之间是串行的。
- 回调必须短小,不能长时间阻塞。
- 耗时工作应通过Queue或Notification交给普通任务。
- 单次Timer到期后停止。
- 自动重载Timer到期后安排下一周期。
FreeRTOS软件定时器用于:
经过一段时间后执行回调
或者
按照固定周期反复执行回调
创建定时器
周期定时器
static TimerHandle_t xPeriodicTimer = NULL;
//名称:Periodic, 周期:400 Tick, 自动重载:pdTRUE, Timer ID:NULL,回调函数:vPeriodicTimerCallback
xTimerCreate("Periodic",pdMS_TO_TICKS(400),pdTRUE,NULL,vPeriodicTimerCallback);
static void vPeriodicTimerCallback(TimerHandle_t xTimer)
{
if (condition)
{
(void)xTimerStop(xTimer, 0); //主动停止周期定时器
}
}
单次定时器
static TimerHandle_t xOneShotTimer = NULL;
//名称:Periodic, 周期:100Tick, 自动重载:pdFALSE, Timer ID:NULL,回调函数:vOneShotTimerCallback
xTimerCreate("OneShot",pdMS_TO_TICKS(100),pdFALSE,NULL,vOneShotTimerCallback);
static void vOneShotTimerCallback(TimerHandle_t xTimer)
{
(void)xTimer;
}
启动定时器
//启动哪个定时器,第二个参数:向Timer命令队列发送启动命令时,最多等待多少Tick
BaseType_t xPeriodicStartResult = xTimerStart(xPeriodicTimer, 0);
BaseType_t xOneShotStartResult = xTimerStart(xOneShotTimer, 0);
软件定时器不是独立任务
每个软件定时器并没有自己的任务和任务栈。
FreeRTOS只创建一个公共任务:
Timer Service Task
也称:
Timer Daemon Task
所有软件定时器回调都由这个任务执行:
Timer Service Task
├── 调用Periodic回调
├── 调用One-shot回调
└── 调用其他软件定时器回调
所以定时器回调是串行执行的,不会同时运行。
Timer Service Task优先级
配置:
#define configTIMER_TASK_PRIORITY \
(configMAX_PRIORITIES - 1)
回调不能阻塞
所有Timer共享一个Timer Service Task。
因此Timer回调中不要使用:
vTaskDelay()
xQueueReceive(..., portMAX_DELAY)
xSemaphoreTake(..., portMAX_DELAY)
长时间循环
慢速外设操作
回调中应该做什么
推荐:
设置标志
发送任务通知
发送短队列消息
启动或停止另一个Timer
常用Timer API
xTimerCreate() /* 创建 */
xTimerStart() /* 启动 */
xTimerStop() /* 停止 */
xTimerReset() /* 从当前时刻重新计时 */
xTimerChangePeriod() /* 修改周期 */
xTimerDelete() /* 删除 */
xTimerIsTimerActive() /* 查询是否活动 */