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)
相关推荐
Natural_yz1 小时前
大数据学习17之Spark-Core
大数据·学习·spark
qq_172805591 小时前
RUST学习教程-安装教程
开发语言·学习·rust·安装
一只小小汤圆1 小时前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
虾球xz2 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
LateBloomer7772 小时前
FreeRTOS——信号量
笔记·stm32·学习·freertos
legend_jz2 小时前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
Komorebi.py2 小时前
【Linux】-学习笔记04
linux·笔记·学习
wenchm2 小时前
细说STM32单片机DMA中断收发RTC实时时间并改善其鲁棒性的另一种方法
stm32·单片机·嵌入式硬件
weiabc2 小时前
学习electron
javascript·学习·electron
HackKong3 小时前
小白怎样入门网络安全?
网络·学习·安全·web安全·网络安全·黑客