一、定时器概念
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);