RT_Thread应用13—软件定时器1

本文深入解析RT-Thread操作系统中的软件定时器功能,包括其运作机制、应用场景及精度控制。介绍了定时器的创建、启动、停止和删除流程,以及如何避免在超时函数中使用阻塞性API。

第二十二 软件定时器(第一部分)

一、概念

定时器,是指从指定的时刻开始,经过一个指定时间,然后触发一个超时事件,用户可以自定义定时器的周期与频率。如:闹钟
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
超时函数需要注意

  • 需要快进快出
  • 不能有任何阻塞线程运行的情况,如 rt_thread_delay()以及其它能阻塞线程运行的函数
  • 两次触发超时函数的时间间隔 Tick 叫定时器的定时周期。

RT-Thread 软件定时器功能上支持:

  • 静态裁剪:能通过宏关闭软件定时器功能。

  • 软件定时器创建。

  • 软件定时器启动。

  • 软件定时器停止。

  • 软件定时器删除。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、应用场景

在这里插入图片描述

三、定时器的精度

  • 软件定时器以系统节拍周期为计时单位。系统节拍是系统的心跳节拍,表示系统时钟的频率,类似于人的心跳,1s 能跳动多少下,系统节拍配置为 RT_TICK_PER_SECOND,默认是 1000。那么系统的时钟节拍周期就为 1ms(1s 跳动 1000 下,每一下就为 1ms)。

  • 软件定时器的所定时数值必须是这个节拍周期的整数倍
    例如节拍周期是 10ms,那么上层软件定时器定时数值只能是 10ms,20ms,100ms 等,而不能取值为 15ms。

  • 由于节拍定义了系统中定时器能够分辨的精确度,系统可以根据实际系统 CPU 的处理能力和实时性需求设置合适的数值,
    ————系统节拍周期的值越小,精度越高,但是系统开销也将越大

四、 软件定时器的运作机制

软件定时器是系统资源,创建定时器的时候会分配一块内存空间。
在这里插入图片描述
重要的全局变量:
rt_tick:它是一个 32 位无符号的变量,用于记录当前系统经过的 tick 时间,当硬件定时器中断来临时,它将自动增加 1。

软件定时器列表 rt_soft_timer_list:系统新创建并激活的定时器都会以超时时间****升序 的 方 式 插 入 到 列 表 中

在这里插入图片描述
例子:
在这里插入图片描述
在定时器链表中插入过程在这里插入图片描述
在这里插入图片描述
问:系统如何处理软件定时器列表?
ANS:系统在不断运行, rt_tick 随着 SysTick 的触发一直在增长(每一次硬件定时器中断来临,rt_tick 变量会加 1),会比较当前系统时间 rt_tick 是否大于或等于 timeout。
若是则表示超时,定时器线程调用对应定时器的超时函数,否则退出软件定时器线程 。
在这里插入图片描述
如:在创建定 Timer1 并且启动后,假如系统经过了 50 个tick, rt_tick 从 0 增长到 50, rt_tick = Timer1 的 timeout 值, 这时会触发与 Timer1 对应的超
时函数,从而转到超时函数中执行用户代码,同时将 Timer1 从 rt_timer_list 删除。
在 rt_tick=40 的时候创建的 Timer3,在经过 130 个 tick 后(此时系统时间 rt_tick 是 40,130个 tick 就是系统时间 rt_tick 为 170 的时候),与 Timer3 定时器对应的超时函数会被触发,接着将 Timer3 从 rt_timer_list 删除。

需要注意

  • 软件定时器的超时函数中应快进快出,绝对不允许使用任何可能引软件定时器起线程挂起或者阻塞的 API 接口,在超时函数中也绝对不允许出现死循环。
  • 软件定时器使用了系统的一个队列和一个线程资源,软件定时器线程的优先级默认为 RT_TIMER_THREAD_PRIO。
  • 创建单次软件定时器,该定时器超时执行完超时函数后,系统会自动删除该软件定时器,并回收资源。
  • 定时器线程的堆栈大小默认为 RT_TIMER_THREAD_STACK_SIZE,512 个字节。
### RT-Thread 动态定时器与静态定时器的区别 #### 定义与分配方式 动态定时器是指在程序运行过程中通过调用 API 函数来创建的定时器。这类定时器允许灵活地调整参数,在不再需要时也可以销毁,从而节省资源。 静态定时器则是在编译阶段就已经定义好的定时器对象,通常作为全局变量存在于代码中。这种方式减少了运行时创建和销毁定时器所带来的开销,适用于那些生命周期贯穿整个应用程序始终存在的定时需求[^2]。 #### 内存管理 对于动态定时器而言,其占用的内存是从堆空间中分配出来的;而静态定时器由于是在编译期就已知大小并固定下来的结构体实例,因此它们直接驻留在数据段内,不涉及额外的内存分配操作。 #### 使用场景 当应用逻辑较为复杂且存在多个不同周期的任务调度需求时,采用动态定时器会更加合适,因为可以根据实际情况按需启动或停止特定任务对应的计时过程。相反,如果某些功能模块具有固定的延时特性,则更适合使用静态定时器实现,这样不仅简化了编程模型还提高了系统的实时响应性能。 ```c // 创建一个动态定时器的例子 rt_timer_t dynamic_timer; dynamic_timer = rt_timer_create("dyna", callback_function, RT_NULL, 1000, RT_TIMER_FLAG_ONE_SHOT); if (dynamic_timer != RT_NULL){ rt_timer_start(dynamic_timer); } // 声明一个静态定时器的例子 static struct rt_timer static_timer; int init_static_timer(void) { /* 初始化 */ rt_err_t result; result = rt_timer_init(&static_timer,"stat",callback_function,RT_NULL,1000, RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_HARDWARE); if(result == RT_EOK) rt_timer_start(&static_timer); return result; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值