基本知识
RT-Thread 中,时钟节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒
获取时钟节拍
rt_tick_t rt_tick_get(void);
定时器分类
- 硬件定时器
- 软件定时器
触发方式分类
- 单次触发
- 周期触发
HARD_TIMER 模式
- HARD_TIMER 模式的定时器超时函数在中断上下文环境中执行,可以在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_HARD_TIMER 来指定。
- 对于超时函数的要求与中断服务例程的要求相同:执行时间应该尽量短,执行时不应导致当前上下文挂起、等待
- RT-Thread 定时器默认的方式是 HARD_TIMER 模式
SOFT_TIMER 模式
SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行
RT_USING_TIMER_SOFT
RT_TIMER_FLAG_SOFT_TIMER
定时器控制块
struct rt_timer
{
struct rt_object parent;
rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL]; /* 定时器链表节点 */
void (*timeout_func)(void *parameter); /* 定时器超时调用的函数 */
void *parameter; /* 超时函数的参数 */
rt_tick_t init_tick; /* 定时器初始超时节拍数 */
rt_tick_t timeout_tick; /* 定时器实际超时时的节拍数 */
};
typedef struct rt_timer *rt_timer_t;
定时器的管理方式
在系统启动时需要初始化定时器管理系统。可以通过下面的函数接口完成
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);
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 /* 软件定时器 */
删除动态定时器
rt_err_t rt_timer_delete(rt_timer_t timer);
静态定时器
创建
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_err_t rt_timer_detach(rt_timer_t timer);
启动和停止定时器
启动
rt_err_t rt_timer_start(rt_timer_t timer);
停止
rt_err_t rt_timer_stop(rt_timer_t timer);
控制定时器
rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void* arg);
cmd可选:
#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 /* 设置定时器为周期型定时器 */
使用示例:
#include <rtthread.h>
/* 定时器的控制块 */
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\n", cnt);
/* 运行第 10 次,停止周期定时器 */
if (cnt++>= 9)
{
rt_timer_stop(timer1);
rt_kprintf("periodic timer was stopped! \n");
}
}
/* 定时器 2 超时函数 */
static void timeout2(void *parameter)
{
rt_kprintf("one shot timer is timeout\n");
}
int timer_sample(void)
{
/* 创建定时器 1 周期定时器 */
timer1 = rt_timer_create("timer1", timeout1,
RT_NULL, 10,
RT_TIMER_FLAG_PERIODIC);
/* 启动定时器 1 */
if (timer1 != RT_NULL) rt_timer_start(timer1);
/* 创建定时器 2 单次定时器 */
timer2 = rt_timer_create("timer2", 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);