定时器管理接口
定时器管理系统初始化
初始化定时器管理系统,可以通过下面的函数接口完成:
void rt_system_timer_init(void);
函数参数
无
函数返回
无
如果需要使用SOFT_TIMER,则系统初始化时,应该调用下面这个函数接口:
void rt_system_timer_thread_init(void);
函数参数
无
函数返回
无
创建定时器
当动态创建一个定时器时,可使用下面的函数接口:
rt_timer_t rt_timer_create(const char* name,
void (*timeout)(void* parameter), void* parameter,
rt_tick_t time, rt_uint8_t flag);
调用该函数接口后,内核首先从动态内存堆中分配一个定时器控制块,然后对该控制块进行基本的初始化。
函数参数
参数 描述
const char* name 定时器的名称;
void (timeout)(void parameter) 定时器超时函数指针(当定时器超时时,系统会调用这个函数);
void* parameter 定时器超时函数的入口参数(当定时器超时时,调用超时回调函数
会把这个参数做为入口参数传递给超时函数);
rt_tick_t time 定时器的超时时间,单位是系统节拍;
rt_uint8_t flag 定时器创建时的参数,支持的值包括(可以用“或”关系取多个值);
include/rtdef.h中定义了一些定时器相关的宏,如下。
#define RT_TIMER_FLAG_DEACTIVATED 0x0 /* 定时器为非激活态 */
#define RT_TIMER_FLAG_ACTIVATED 0x1 /* 定时器为激活状态 */
#define RT_TIMER_FLAG_ONE_SHOT 0x0 /* 单次定时 */
#define RT_TIMER_FLAG_PERIODIC 0x2 /* 周期定时 */
#define RT_TIMER_FLAG_HARD_TIMER 0x0 /* 硬件定时器 */
#define RT_TIMER_FLAG_SOFT_TIMER 0x4 /* 软件定时器 */
当指定的flag为RT_IMER_FLAG_HARD_TIMER时,如果定时器超时,定时器的回调函数将在时钟中断的服务例程上下文中被调用;当指定的flag为RT_TIMER_FLAG_SOFT_TIMER时,如果定时器超时,定时器的回调函数将在系统时钟timer线程的上下文中被调用。
函数返回
如果定时器创建成功,则返回定时器的句柄;如果创建失败,会返回RT_NULL(通常会由于系统内存不够用而返回RT_NULL)。
创建定时器的例子如下所示:
/*
- 程序清单:动态定时器例程
- 这个例程会创建两个动态定时器对象,一个是单次定时,一个是周期性的定时
*/
#include <rtthread.h>
/* 定时器的控制块 */
static rt_timer_t timer1;
static rt_timer_t timer2;
/* 定时器1超时函数 */
static void timeout1(void* parameter)
{
rt_kprintf("periodic timer is timeout\n");
}
/* 定时器2超时函数 */
static void timeout2(void* parameter)
{
rt_kprintf("one shot timer is timeout\n");
}
int rt_application_init(void)
{
timer1 = rt_timer_create("timer1",
timeout1,
RT_NULL,
10,
RT_TIMER_FLAG_PERIODIC);
if (timer1 != RT_NULL) rt_timer_start(timer1);
timer2 = rt_timer_create("timer2",
timeout2,
RT_NULL,
30,
RT_TIMER_FLAG_ONE_SHOT);
if (timer2 != RT_NULL) rt_timer_start(timer2);
return 0;
}
删除定时器
系统不再使用特定定时器时,可使用下面的函数接口:
rt_err_t rt_timer_delete(rt_timer_t timer);
调用这个函数接口后,系统会把这个定时器从rt_timer_list链表中删除,然后释放相应的定时器控制块占有的内存。
函数参数
参数 描述
rt_timer_t timer 定时器句柄,指向要删除的定时器。
函数返回
返回RT_EOK (如果参数timer句柄是一个RT_NULL,将会导致一个ASSERT断言)
删除定时器的例子请参考例9-1中删除定时器的代码。
初始化定时器
当选择静态创建定时器时,可利用rt_timer_init接口来初始化该定时器,函数接口如下:
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_t timer 定时器句柄,指向要初始化的定时器控制块;
const char* name 定时器的名称;
void (timeout)(void parameter) 定时器超时函数指针(当定时器超时时,系统会调用这个函数);
void* parameter 定时器超时函数的入口参数(当定时器超时时,调用超时回调函数
会把这个参数做为入口参数传递给超时函数);
rt_tick_t time 定时器的超时时间,单位是系统节拍;
rt_uint8_t flag 定时器创建时的参数,支持的值包括(可以用“或”关系取多个值);
#define RT_TIMER_FLAG_ONE_SHOT 0x0 /* 单次定时 */
#define RT_TIMER_FLAG_PERIODIC 0x2 /* 周期定时 */
#define RT_TIMER_FLAG_HARD_TIMER 0x0 /* 硬件定时器 */
#define RT_TIMER_FLAG_SOFT_TIMER 0x4 /* 软件定时器 */
当指定的flag为RT_IMER_FLAG_HARD_TIMER时,如果定时器超时,定时器的回调函数将在时钟中断的服务例程上下文中被调用;当指定的flag为RT_TIMER_FLAG_SOFT_TIMER时,如果定时器超时,定时器的回调函数将在系统时钟timer线程的上下文中被调用。
初始化定时器的例子如下代码所示:
/*
- 程序清单:静态定时器例程
- 这个程序会初始化2个静态定时器,一个是单次定时,一个是周期性的定时
*/
#include <rtthread.h>
/* 定时器的控制块 */
static struct rt_timer timer1;
static struct rt_timer timer2;
/* 定时器1超时函数 */
static void timeout1(void* parameter)
{
rt_kprintf("periodic timer is timeout\n");
}
/* 定时器2超时函数 */
static void timeout2(void* parameter)
{
rt_kprintf("one shot timer is timeout\n");
}
int rt_application_init(void)
{
rt_timer_init(&timer1, "timer1",
timeout1,
RT_NULL,
10,
RT_TIMER_FLAG_PERIODIC);
rt_timer_init(&timer2, "timer2",
timeout2,
RT_NULL,
30,
RT_TIMER_FLAG_ONE_SHOT);
rt_timer_start(&timer1);
rt_timer_start(&timer2);
return 0;
}
脱离定时器
当一个静态定时器不需要再使用时,可以使用下面的函数接口:
rt_err_t rt_timer_detach(rt_timer_t timer);
脱离定时器时,系统会把定时器对象从系统容器的定时器链表中删除,但是定时器对象所占有的内存不会被释放。
函数参数
参数 描述
rt_timer_t timer 定时器句柄,指向要脱离的定时器控制块。
函数返回
返回RT_EOK。
脱离定时器的例子可参考9-2例程代码中的脱离部分。
启动定时器
当定时器被创建或者初始化以后,并不会被立即启动,必须在调用启动定时器函数接口后,才开始工作,启动定时器函数接口如下:
rt_err_t rt_timer_start(rt_timer_t timer);
调用定时器启动函数接口后,定时器的状态将更改为激活状态(RT_TIMER_FLAG_ACTIVATED),并按照超时顺序插入到rt_timer_list队列链表中。
函数参数
参数 描述
rt_timer_t timer 定时器句柄,指向要启动的定时器控制块。
函数返回
如果timer已经处于激活状态,则返回-RT_ERROR;否则返回RT_EOK。
启动定时器的例子请参考9-1例程代码中的定时器代码。
停止定时器
启动定时器以后,若想使它停止,可以使用下面的函数接口:
rt_err_t rt_timer_stop(rt_timer_t timer);
调用定时器停止函数接口后,定时器状态将更改为停止状态,并从rt_timer_list链表中脱离出来不参与定时器超时检查。当一个(周期性)定时器超时时,也可以调用这个函数接口停止这个(周期性)定时器本身。
函数参数
参数 描述
rt_timer_t timer 定时器句柄,指向要停止的定时器控制块。
函数返回
如果timer已经处于停止状态,返回-RT_ERROR;否则返回RT_EOK。
控制定时器
除了上述提供的一些编程接口,RT_thread也额外提供了定时器控制函数接口,以获取或设置更多定时器的信息。控制定时器函数接口如下:
rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void* arg);
控制定时器函数接口可根据命令类型参数,来查看或改变定时器的设置。
函数参数
参数 描述
rt_timer_t timer 定时器句柄,指向要进行控制的定时器控制块;
rt_uint8_t cmd 用于控制定时器的命令,当前支持四个命令接口,分别是设置
定时时间,查看定时时间,设置单次触发,设置周期触发;
void* arg 与command相对应的控制命令参数;
#define RT_TIMER_CTRL_SET_TIME 0x0 /* 设置定时器超时时间 */
#define RT_TIMER_CTRL_GET_TIME 0x1 /* 获得定时器超时时间 */
#define RT_TIMER_CTRL_SET_ONESHOT 0x2 /* 设置定时器为单一超时型 */
#define RT_TIMER_CTRL_SET_PERIODIC 0x3 /* 设置定时器为周期型定时器 */
函数返回
函数返回RT_EOK
使用定时器控制接口的代码如下所示:
/*
- 程序清单:定时器控制接口示例
- 这个例程会创建1个动态周期型定时器对象,然后控制它进行更改定时器的时间长度。
*/
#include <rtthread.h>
/* 定时器的控制块 */
static rt_timer_t timer1;
static rt_uint8_t count;
/* 定时器超时函数 */
static void timeout1(void* parameter)
{
rt_kprintf("periodic timer is timeout\n");
count ++;
if (count >= 8)
{
int timeout_value = 50;
rt_timer_control(timer1, RT_TIMER_CTRL_SET_TIME, (void*)&timeout_value);
count = 0;
}
}
int rt_application_init(void)
{
timer1 = rt_timer_create("timer1",
timeout1,
RT_NULL,
10,
RT_TIMER_FLAG_PERIODIC);
if (timer1 != RT_NULL)
rt_timer_start(timer1);
return 0;
}
原作者:RT-Thread编程手册