3.2 数据结构 软件定时器的数据结构决定了其执行的性能和功能,一般可分为两种:数组结构和链表结构。什么意思呢?这是(多个)软件定时器在内存中的存储方式,可以用数组来存,也可以用链表来存。 两者的优劣之分就是两种数据结构的特性之分:数组方式的定时器查找较快,但数量固定,无法动态变化,数组大了容易浪费内存,数组小了又可能不够用,适用于定时事件明确且固定的系统。 链表方式的定时器数量可动态增减,易造成内存碎片(如果没有内存管理),查找的时间开销相对数组大,适用于通用性强的系统,Linux,uC/OS,FreeRTOS等操作系统用的都是链表式的软件定时器。 本文使用数组结构: static softTimer timer[TIMER_NUM]; //软件定时器数组
数组和链表是软件定时器整体的数据结构,当具体到单个定时器时,就涉及软件定时器结构体的定义,软件定时器所具有的功能与其结构体定义密切相关,以下是本文中软件定时器的结构体定义: typedef struct softTimer {
uint8_t state; //状态
uint8_t mode; //模式
uint32_t match; //到期时间
uint32_t period; //定时周期
callback *cb; //回调函数指针
void *argv; //参数指针
uint16_t argc; //参数个数
}softTimer;
定时器的状态共有三种,默认是停止,启动后为运行,到期后为超时。 typedef enum tmrState {
SOFT_TIMER_STOPPED = 0, //停止
SOFT_TIMER_RUNNING, //运行
SOFT_TIMER_TIMEOUT //超时
}tmrState;
模式有两种:到期后就停止的是单次模式,到期后重新定时的是周期模式。 typedef enum tmrMode {
MODE_ONE_SHOT = 0, //单次模式
MODE_PERIODIC, //周期模式
}tmrMode;
不管哪种模式,定时器到期后,都将执行回调函数,以下是该函数的定义,参数指针argv为void指针类型,便于传入不同类型的参数。 typedef void callback(void *argv, uint16_t argc);
上述结构体中的模式state和回调函数指针cb是可选的功能,如果系统不需要周期执行的定时器,或者不需要到期后自动执行某个函数,可删除此二者定义。
|