RT_Thread_软件定时器

1、定时器分类

1.1、硬件定时器(MCU提供)

精度很高,可以达到纳秒级别,并且是中断触发方式。

由外部晶振提供给芯片输入时钟,到达设定时间值后芯片中断控制器产生时钟中断。

1.2、软件定时器(OS提供)

定时数值必须是 时钟节拍(OS Tick)的整数倍

  • HARD_TIMER模式

RT-Thread 定时器默认的方式是 HARD_TIMER 模式,即定时器超时后,超时函数是在系统时钟中断的上下文环境中运行的。

  • SOFT_TIMER模式

通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式;在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_SOFT_TIMER 来指定设置 SOFT_TIMER 模式。

SOFT_TIMER 模式的定时器超时函数在 timer 线程的上下文环境中执行。

2、定时器工作机制

2.1、rt_tick加1

2.2、定时器链表 rt_timer_list

超时时间排序的方式插入到 rt_timer_list 链表中。

如下图,定时器链表中超时时间timeout由小到大排序的,如果又有定时器timer4被激活,超时时间在330的话,会插到timer2和timer3之间。

当系统节拍rt_tick增加到70时timer1执行,rt_tick=120时timer2执行.......

 

3、定时器控制块

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;

4、定时器API

4.1、系统初始化

在系统初始化时,默认调用1是HARD_TIMER模式,如果想用SOFT_TIMER要调用2

1、void rt_system_timer_init(void);
2、void rt_system_timer_thread_init(void);

4.2、创建和删除定时器

  • 动态定时器
rt_timer_t rt_timer_create(const char* name,
                           void (*timeout)(void* parameter),
                           void* parameter,
                           rt_tick_t time,
                           rt_uint8_t flag);
参数描述
name定时器的名称
void (timeout) (void parameter)定时器超时函数指针(当定时器超时时,系统会调用这个函数)
parameter定时器超时函数的入口参数
time定时器的超时时间,单位是时钟节拍
flag

单次定时RT_TIMER_FLAG_ONE_SHOT、周期定时RT_TIMER_FLAG_PERIODIC、

硬件模式RT_TIMER_FLAG_HARD_TIMER、软件模式RT_TIMER_FLAG_SOFT_TIMER;

(可以用 “或” 关系取多个值)

返回——
RT_NULL创建失败(通常会由于系统内存不够用而返回 RT_NULL)
定时器的句柄定时器创建成功
rt_err_t rt_timer_delete(rt_timer_t timer);
参数描述
timer定时器句柄,指向要删除的定时器
返回——
RT_EOK删除成功(如果参数 timer 句柄是一个 RT_NULL,将会导致一个 ASSERT 断言)
  • 静态定时器
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);

4.3、启动和停止定时器

  • 启动定时器

启动定时器后,定时器的状态将更改为激活状态(RT_TIMER_FLAG_ACTIVATED),并按照超时顺序插入到 rt_timer_list 队列链表中;

rt_err_t rt_timer_start(rt_timer_t timer);
参数描述
timer定时器句柄,指向要启动的定时器控制块
返回——
RT_EOK启动成功
  • 停止定时器 
rt_err_t rt_timer_stop(rt_timer_t timer);
参数描述
timer定时器句柄,指向要停止的定时器控制块
返回——
RT_EOK成功停止定时器
- RT_ERRORtimer 已经处于停止状态

5、例程

HARD_TIMER模式;

定时器1是周期性定时器,超时时间是10倍(OS Tick),执行10次后调用rt_timer_stop停止;

定时器2是单次定时器,超时时间是30倍(OS Tick),执行1次后自动停止;

#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);
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值