Skip to content

为什么需要定时器?——定时器的应用场景

李述铜

770字约3分钟

2025-08-30

在很多时候,系统中需要周期性地做某些事情,或者推迟执行某件事,此时可以借助定时器来实现这些功能。

什么是定时器?

RT-Thread中的定时器是一个“”的延迟或周期执行工具,它不依赖任务执行,而是****中被调度触发,执行预设的

alt text

它与任务中使用延时函数有着不同的特性,具体来说有如下几个方面:

特性延时函数(如rt_thread_delay()定时器
执行者当前任务本身系统 tick 定时触发回调
是否阻塞阻塞当前任务非阻塞
使用场景任务内部临时等待轻量定时触发任务逻辑
执行位置任务上下文中断上下文(或任务上下文)

典型应用场景

通常情况下,我们常常将定时器用于以下几种场合。虽然在这些场合中可以使用硬件定时器实现相同的功能;但是,硬件定时器毕竟有限,于是就需要利用RT-Thread提供的定时器。

1. 周期性任务调度

例如:LED 心跳灯、状态刷新。每隔一秒刷新一次界面、闪一次灯,不需要一个完整的任务做这件事。

如果单独创建一个任务来完成这些简单的工作,则过于浪费任务资源。

2. 超时检测机制

例如:串口接收超时、按键长按。如果在一定时间内没收到数据,说明通信异常,可以重连。

3. 替代任务延时函数,提高响应效率

在任务中,可以避免使用rt_thread_mdelay()等函数,而是在事件发生时被定时器唤醒或回调执行。这样任务就可以尽早做某它事情。

4. 软件看门狗

定时执行一个喂狗操作,防止系统死锁。

5. 延迟启动某项功能

例如,设备开机后延迟5秒启动某个服务。

案例演示:定时闪烁LED(1秒闪一次)

下面的示例使用一个定时器,每隔 1 秒切换一次 LED 状态。

#include <rtthread.h>
#include "base.h" 
#include "rtconfig.h"

// 回调函数
static void led_timer_cb(void *parameter) {
    RT_UNUSED(parameter);
    led_toggle(LED0);  // 切换LED 状态
}

int main (void) {
    // 创建一个周期性定时器(1000ms)
    rt_timer_t led_timer = rt_timer_create("led_t",
                                led_timer_cb,
                                RT_NULL,
                                rt_tick_from_millisecond(500),  // RT_TICK_PER_SECOND, 
                                RT_TIMER_FLAG_PERIODIC);

    if (led_timer != RT_NULL) {
        rt_timer_start(led_timer);  // 启动定时器
    }

    return 0;
}

可以看到:如果要使用定时器,我们需要先创建定时器再启动(与任务创建相同)。但是,当定时器启动后,系统会根据定时器的要求周期性(或一次性)的调用定时器指定的回调函数。