1. 软件定时器是由操作系统提供的一:类系统接口,它构建在硬件定时器基础之上(系统滴答定时器)。软件定时器使系统能够提供不受数目限制的定时器服务。
RT-Thread操作系统提供的软件定时器,以系统节拍(OS tick)的时间长度为定时单位,提供了基于系统节拍整数倍的定时能力,即定时数值是OSTick的整数倍。例如一个OS Tick是10ms,那么上层软件定时器只能提供10ms,20ms,, 100ms等时间精度的定时服务,而不能定时为15ms、25ms、35ms等。
当软件定时器所设定的定时时间到了后,会调用用户设置的定时器timeout回调函数,用户需要定时运行的程序会在回调函数中得到处理。
2. 定时模式
HARDTIMER模式
HARD_ _TIMER 模式的定时器超时函数在中断上下文环境中执行,此模式在定时器初始化时指定。在中断上下文环境中执行时,对于超时函数的要求与中断服务例程的要求相同:执行时间应该尽量短,执行时不应导致当前,上”下文挂起。HARD_ TIMER 模式是RT-Thread软件定时器的默认方式。
SOFTTIMER模式
SOFTTIMER模式的定时器超时函数在系统的timer线程的线程上下文中执行。通过宏定义RT_USING_TIMER_SOFT 来决定是否启用该模式。当启用SOFTTIMER模式后,我们可以在定时器初始化时指定定时器工作在SOFTTIMER模式。
3. 软件定时器控制块
在RTT中,软件定时器控制块是操作系统用于管理软件定时器的一个数据结构
struct rt_timer
{
struct rt_object parent;
rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL];//定时器列表节点
void (*timeout_func)(void *parameter); //超时函数的函数指针,传入函数给指针
void *parameter; //超时函数的参数,不用时赋值0
rt_tick_t init_tick; //定时器超时 时间,超时时间到了就调用超时函数。以系统节拍为时间单位
rt_tick_t timeout_tick;
}
typedef struct rt_timer *rt_time_t
定义静态软件定时器:struct rt_timer static_timer;
定义动态软件定时器:rt_timer_t dynamic_timer;
4. 系统提供一组API对定时器的操作
静态定时器的初始化与脱离
void rt_timer_init(rt_timer_t timer,const char *name,void (*timeout)(void *parameter),
void *parameter,rt_tick_t time,rt_uint8_t flag)
/*第一个参数是说明定时器控制块的地址,指明那个软件定时器。第三个参数就是把一个函数给到函数指针,即回调函数,回调函数先写好后传入地址。第四个参数是回调函数的参数。第五个参数是指定软件定时器超时时间,以系统节拍为单位。最后一个参数可以选择定时器工作模式:RT_TIMER_FLAG_ONE_SHOT(指定超时到了第三个函数运行的次数,即只执行一次回调函数),RT_TIMER_FLAG_PERIODIC(周期性执行回调函数),RT_TIME_FLAG_HARD_TIMER(软件定时器工作在硬件模式),RT_TIMER_FLAG_SOFT_TIMER(软件模式)*/
//flag参数在前两个选一个在或上后两个中的一个。
rt_err_t rt_timer_detach(rt_timer_t timer)
动态定时器的创建与删除
rt_timer_t rt_rimer_creater(const char*name,void (*timeout)(void *parameter),
void *parameter,rt_tick_t time,rt_uint8_t flag)
//参数含义和静态初始化的API一样
rt_err_t rt_timer_delete(rt_timer_t timer)
定时器启动
rt_err_t rt_timer_start(rt_timer_t timer)
定时器停止
rt_err_t rt_timer_stop(rt_timer_t timer)
5. 软件定时器使用示例
在timer_sample.c中
/*
* 程序清单:定时器例程
*
* 这个例程会创建两个动态定时器,一个是单次定时,一个是周期性定时
* 并让周期定时器运行一段时间(10次)后停止运行
*/
#include
/* 定时器的控制块 */
static rt_timer_t timer1;
static rt_timer_t timer2;
static int cnt = 0;
/* 定时器1超时函数 */
static void timeout1(void *parameter)
{
rt_kprintf("periodic timer is timeout %d
", cnt);
/* 运行第10次,停止周期定时器 */
if (cnt++ >= 9)
{
rt_timer_stop(timer1);
rt_kprintf("periodic timer was stopped!
");
}
}
/* 定时器2超时函数 */
static void timeout2(void *parameter)
{
rt_kprintf("one shot timer is timeout
");
}
int timer_sample(void)
{
/* 创建定时器1 周期定时器 */
timer1 = rt_timer_create("timer1", timeout1, //回调函数为timeout1
RT_NULL, 10,
RT_TIMER_FLAG_PERIODIC);//周期执行会回调函数。
/* 启动定时器1 */
if (timer1 != RT_NULL) rt_timer_start(timer1);
/* 创建定时器2 单次定时器 */
timer2 = rt_timer_create("timer2", timeout2,//回调函数timeout2
RT_NULL, 30,
RT_TIMER_FLAG_ONE_SHOT);//执行一次回调函数
/* 启动定时器2 */
if (timer2 != RT_NULL) rt_timer_start(timer2);
return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(timer_sample, timer sample);
原作者:Surferqing_
|