【rtthread内核系列】第一篇:定时器

一、定时器概念

1.1 时钟节拍

时钟节拍是系统的最小时间单位,宏RT_TICK_PER_SECOND为100时,一个时钟节拍的时间为10ms,时钟节拍也是线程时间片的最小单位。在stm32中,时钟节拍通过systick中断实现,在每次systick中断,全局变量rt_tick加1。

void SysTick_Handler(void)
{
    
    
    /* 进 入 中 断 */
    rt_interrupt_enter();
    ……
    rt_tick_increase();
    /* 退 出 中 断 */
    rt_interrupt_leave();
}

获取当前的时钟节拍rt_tick可以通过rt_tick_get函数获得。

1.2 rtthread定时器

1.2.1 rtthread定时器概念

rtthread定时器的定时时间以时钟一个节拍的时间为单位,创建并激活的定时器会以超时时间的大小排序,链接在rt_timer_list上,在每次硬件中断执行rt_tick_increase调用 rt_timer_check时判断是否产生超时事件。

1.2.2 rtthread定时器模式

  • HARD_TIMER :定时器超时函数在硬件systick中断的上下文进行,需要注意执行时间尽量短,不执行内存的申请和释放操作,不能执行会挂起的函数。
  • SOFT_TIMER:通过 RT_USING_TIMER_SOFT决定是否开启此功能,系统会在初始化时创建一个timer线程,这种模式的定时器的超时函数的上下文是线程。

二、rtthread定时器api

//创建一个定时器
/*
name:定时器名称
timeout:超时函数
parameter:超时函数的参数
time:超时时间,单位:时钟节拍
flag:标志
*/
rt_timer_t rt_timer_create(const char* name,
                                void (*timeout)(void* parameter),
                                void* parameter,
                                rt_tick_t time,
                                rt_uint8_t flag);

//删除时钟
/*
timer:定时器句柄
*/
rt_err_t rt_timer_delete(rt_timer_t timer);

//初始化定时器
/*
timer:定时器句柄
name:定时器名称
timeout:超时函数
parameter:超市函数的参数
time:超时时间,单位:时钟节拍
flag:标志
*/
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);
             
脱离定时器
/*
timer:定时器句柄
*/
rt_err_t rt_timer_detach(rt_timer_t timer);

//启动定时器
/*
timer:定时器句柄
*/
rt_err_t rt_timer_start(rt_timer_t timer);

//停止定时器
/*
timer:定时器句柄
*/
rt_err_t rt_timer_stop(rt_timer_t timer);

//控制定时器
/*
timer:定时器句柄
cmd:控制命令
arg:控制命令参数
*/
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 /* 设 置 定 时 器 为 周 期 型 定 时 器 */

三、示例

本示例创建了一个周期性定时器timer1,一个一次性定时器timer2,rtthread默认的定时器工作模式是HARD_TIMER模式,满足超时时间后执行timeout1和timeout2。 周期性定时器执行10次定时任务后停止定时器。

/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-08-24     yangjie      the first version
 */

/*
* 程序清单:定时器例程
*
* 这个例程会创建两个动态定时器,一个是单次定时,一个是周期性定时
* 并让周期定时器运行一段时间后停止运行
*/
#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);

猜你喜欢

转载自blog.csdn.net/weixin_43810563/article/details/116721941