RTT学习

定时器的管理方式

在系统启动时需要初始化定时器管理系统。

c 复制代码
void rt_system_timer_init(void);

如果需要使用SOFT_TIMER,则系统初始化时,应该调用

c 复制代码
void rt_system_timer_thread_init(void);

定时器控制块中含有定时器相关的重要参数,在定时器各种状态间起到纽带的作用。

定时器的相关操作如图所示,对定时器的操作包含:创建/初始化定时器、启动定时器、运行定时器、删除/脱离定时器。

所有定时器在定时超时后都会从定时器链表中被移除,而周期性定时器会在它再次启动时被加入定时器链表,这与定时器参数设置相关。

c 复制代码
rt_timer_t rt_timer_create(const char* name,
                           void (*timeout)(void* parameter),
                           void* parameter,
                           rt_tick_t time,
                           rt_uint8_t flag);

调用该函数接口后,内核首先从动态内存堆中分配一个定时器控制块,然后对该控制块进行基本的初始化。

  • time:定时器的超时时间,单位是时钟节拍。
  • flag:定时器创建的参数,支持的值包括单次定时、周期定时、硬件定时器、软件定时器等,可以用或关系取多个值。
c 复制代码
#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     /* 软件定时器   */

上面 2 组值可以以 "或" 逻辑的方式赋给 flag。当指定的 flag 为 RT_TIMER_FLAG_HARD_TIMER 时,如果定时器超时,定时器的回调函数将在时钟中断的服务例程上下文中被调用;当指定的 flag 为 RT_TIMER_FLAG_SOFT_TIMER 时,如果定时器超时,定时器的回调函数将在系统时钟 timer 线程的上下文中被调用。

启动和停止定时器

当定时器被创建或初始化以后,并不会被立即启动,必须在调用启动定时器函数接口后,才开始工作,启动定时器函数接口如下:

c 复制代码
rt_err_t rt_timer_start(rt_timer_t timer);

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

启动定时器以后,若想使它停止:

c 复制代码
rt_err_t rt_timer_stop(rt_timer_t timer);

调用定时器停止函数接口后,定时器状态将更改为停止状态,并从rt_timer_list链表中脱离出来不参与定时器超时检查。
当一个周期性定时器超时时,也可以调用这个函数接口停止这个定时器。

控制定时器

c 复制代码
rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void *arg);
c 复制代码
#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     /* 设置定时器为周期型定时器 */

定时器应用示例

这是一个创建定时器的例子,这个例程会创建两个动态定时器,一个是单次定时,一个是周期性定时并让周期定时器运行一段时间后停止运行。

c 复制代码
#include <rtthread.h>

static rt_timer_t timer1;
static rt_timer_t timer2;
static int cnt = 0;

static void timeout1(void *parameter){
	 rt_kprintf("periodic timer is timeout %d\n", cnt);
	 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){
	timer1 = rt_timer_create("timer1", timeout1, RT_NULL, 10, RT_TIMER_FLAG_PERIODIC);
	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;
}

高精度延时

RTT定时器的最小精度是由系统时钟节拍所决定的(1OS Tick=1/RT_TICK_PER_SECOND秒),定时器设定的时间必须是OS Tick的整数倍。

当需要实现更短时间长度的系统定时时,例如OS Tick是10ms,而程序需要实现1ms的定时或延时,这种时候操作系统定时器将不能够满足要求,只能通过读取系统某个硬件定时器的计数器或直接使用硬件定时器的方式。

在Cortex-M系列中,SysTick已经被RT-Thread用于作为OS Tick使用,它被配置成1/RT_TICK_PER_SECOND秒后触发一次中断的方式。

c 复制代码
void rt_hw_us_delay(rt_uint32_t us)
相关推荐
aloneboyooo6 分钟前
Android学习制作app(ESP8266-01S连接-简单制作)
学习
憨猪在度假17 分钟前
Cmake学习笔记
c++·笔记·学习
学游戏开发的35 分钟前
UE学习日志#19 C++笔记#5 基础复习5 引用1
c++·笔记·学习·游戏引擎·unreal engine
charlie1145141912 小时前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(OLED设备层封装)
c语言·stm32·单片机·教程·oled·嵌入式软件
云山工作室5 小时前
基于fpga技术的脉冲信号源设计(论文+源码)
stm32·嵌入式硬件·fpga开发·毕业设计·毕设
__雨夜星辰__6 小时前
Linux 学习笔记__Day2
linux·服务器·笔记·学习·centos 7
学问小小谢6 小时前
第26节课:内容安全策略(CSP)—构建安全网页的防御盾
运维·服务器·前端·网络·学习·安全
2401_843785238 小时前
STM32 AD多通道
stm32·单片机·嵌入式硬件
厂太_STAB_丝针8 小时前
【自学嵌入式(8)天气时钟:天气模块开发、主函数编写】
c语言·单片机·嵌入式硬件
charlie11451419110 小时前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(协议层封装)
c语言·驱动开发·单片机·学习·教程·oled