以下内容为个人的初学记录,如有错误,欢迎指正。
概述
顾名思义,软件定时器就是用来定时,到了设定的时间(周期)时会执行一些事情(回调函数)。
包括:自动装载定时器(周期性)、一次性定时器:
类似于闹钟,有周期性闹钟和一次性闹钟,周期性闹钟不需要你每天都去设置,但是一次性闹钟在完成一次后就会关闭,需要你手动设置开启;
软件定时器相关的函数,比如xTimerStart()等,虽然是可以在普通的任务中调用,但并没有直接操作定时器,而是把命令发送到定时器命令队列,由DaemonTask(守护任务)读取并对执行和操作相关命令。也就是说,软件定时器是在DaemonTask中被操作的,包括创建、开启等。
DaemonTask优先级为:configTIMER_TASK_PRIORITY;
定时器命令队列的长度:为configTIMER_QUEUE_LENGTH;
当configUSE_TIMERS被设置为1时,在启动调度器时,会自动创建RTOS Damemon Task的任务。它内部可以包含对多个定时器的操作函数。当【命令队列有任务】、【某个定时器超时】时,阻塞的DaemonTask会退出阻塞进入就绪态;
软件定时器工作流程:
- DaemonTask创建定时器,定时器进入冬眠状态(dormant);
- DaemonTask开启定时器,定时器进入运行状态 ;[下图的三个函数(start启动、reset复位、changeperiod修改周期)都能实现开启];
- 如果是【自动装载】,则一直运行,到了定时时间就处理回调函数 1 ;当使用stop函数时进入冬眠;
- 如果时【一次性】,则超时一次,执行回调函数后就进入冬眠;
特别注意,在外部任务调用xTimerStart()不一定能使定时器运行,必须是DaemonTask执行了开启的操作才行。
假设有任务Task和DaemonTask,DaemonTask优先级较低,且处于阻塞。当任务Task调用xTimerStart()发出【开启定时器】的命令时,命令队列有数据使得DaemonTask进入就绪态。但是由于优先级原因,DaemonTask无法开启定时器。
函数
创建
首先是动态创建:
TimerHandle_t xTimerCreate( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction );
返回值:句柄/NULL
pcTimerName:定时器名字
xTimerPeriodInTicks:周期(单位:Tick)
uxAutoReload:pdTRUE-自动装载 / pdFALSE-一次性
pvTimerID:给回调函数使用,用于区分哪个定时器;
pxCallbackFunction:回调函数
静态创建:
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
TickType_t xTimerPeriodInTicks,
UBaseType_t uxAutoReload,
void * pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t *pxTimerBuffer );
删除
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );
由于要向定时器命令队列发送命令,有可能会出现满队列的情况,因此需要xTicksToWait
启动、停止
/*启动*/
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
BaseType_t xTimerStartFromISR(TimerHandle_t xTimer,
BaseType_t *pxHigherPriorityTaskWoken);
/*停止*/
BaseType_t xTimerStop(TimerHandle_t xTimer, TickType_t xTicksToWait);
BaseType_t xTimerStopFromISR(TimerHandle_t xTimer,
BaseType_t *pxHigherPriorityTaskWoken);
复位
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
修改周期
BaseType_t xTimerResetFromISR( TimerHandle_t xTimer,
BaseType_t *pxHigherPriorityTaskWoken );
从定时器被开启到第一次超时,中间的时间应该从开启函数被外部任务调用时开始; ↩︎