聊一下esp_timer

ESP32 里的 esp_timer,这是 ESP-IDF 提供的一个高精度定时器工具,比 FreeRTOS 的软件定时器更直接、更适合硬件相关的场景。

啥是 esp_timer?

想象你在做饭,得精确计时,比如“烤面包 2 分 30 秒,不能差”。普通 FreeRTOS 定时器(xTimer)像个粗糙的闹钟,分秒可能有点飘,但 esp_timer 就像个高精度秒表,能精确到微秒(μs)级别,直接用硬件跑。它特别适合 ESP32 这种嵌入式设备,需要定时干活又不能太依赖任务调度。

简单说:esp_timer 是 ESP32 的硬件定时器接口,准、快、轻量。

基本概念 硬件驱动:它用 ESP32 的硬件定时器(Timer Group),精度高,不受任务切换影响。 单次或周期:可以跑一次(比如“2秒后关灯”),也能循环跑(比如“每秒闪灯”)。 回调函数:到时间后自动调用你写的函数。

怎么用? ESP-IDF 提供了几个简单函数,咱们边讲边试。

1. 创建定时器

先定义一个定时器:

#include "esp_timer.h"

void timer_callback(void *arg) {
    printf("定时器到点了!\n");
}

void app_main() {
    esp_timer_handle_t my_timer;
    const esp_timer_create_args_t timer_args = {
        .callback = timer_callback,  // 回调函数
        .arg = NULL,                 // 传给回调的参数(可选)
        .dispatch_method = ESP_TIMER_TASK, // 在任务中跑回调
        .name = "MyTimer"            // 名字,调试用
    };

    esp_err_t err = esp_timer_create(&timer_args, &my_timer);
    if (err != ESP_OK) {
        printf("创建定时器失败!\n");
    }
}

esptimercreateargst:设置定时器的参数。 callback:到时间后跑的函数。 dispatchmethod:ESPTIMERTASK 表示回调跑在任务里(还有 ESPTIMERISR 直接跑在中断里,后面讲)。 esptimer_create():创建定时器,返回句柄。

2. 启动定时器(单次)

让它跑一次:

void app_main() {
    esp_timer_handle_t my_timer;
    esp_timer_create_args_t timer_args = {
        .callback = timer_callback,
        .arg = NULL,
        .dispatch_method = ESP_TIMER_TASK,
        .name = "MyTimer"
    };

    esp_timer_create(&timer_args, &my_timer);
    esp_timer_start_once(my_timer, 2000000); // 2秒(单位是微秒)
}

esptimerstart_once(定时器, 时间):跑一次,时间单位是微秒(μs),2000000 μs = 2秒。 输出:

(等2秒)
定时器到点了!
  1. 启动定时器(周期) 让它循环跑:
void app_main() {
    esp_timer_handle_t my_timer;
    esp_timer_create_args_t timer_args = {
        .callback = timer_callback,
        .arg = NULL,
        .dispatch_method = ESP_TIMER_TASK,
        .name = "MyTimer"
    };

    esp_timer_create(&timer_args, &my_timer);
    esp_timer_start_periodic(my_timer, 1000000); // 每1秒跑一次
}

esptimerstart_periodic(定时器, 周期):每隔指定时间跑,1000000 μs = 1秒。 输出:

(等1秒)
定时器到点了!
(等1秒)
定时器到点了!
...

4. 完整例子

加个计数器看看效果:

#include "esp_timer.h"

void timer_callback(void *arg) {
    static int count = 0;
    printf("定时器第 %d 次触发\n", ++count);
}

void app_main() {
    esp_timer_handle_t my_timer;
    esp_timer_create_args_t timer_args = {
        .callback = timer_callback,
        .arg = NULL,
        .dispatch_method = ESP_TIMER_TASK,
        .name = "MyTimer"
    };

    esp_timer_create(&timer_args, &my_timer);
    esp_timer_start_periodic(my_timer, 1000000); // 每1秒触发
}

输出:

(等1秒)
定时器第 1 次触发
(等1秒)
定时器第 2 次触发
...

高级用法

1. 停止定时器

不想跑了,可以停:

esp_timer_stop(my_timer); // 停止定时器

单次定时器到时自动停,周期定时器得手动停。

2. 删除定时器

用完清理:

esp_timer_stop(my_timer);       // 先停
esp_timer_delete(my_timer);     // 再删

3. 在中断里跑(ISR 模式)

如果回调很简单(比如置个标志),可以用中断模式:

void IRAM_ATTR timer_callback(void *arg) {
    // 必须放 IRAM,简单操作
    volatile int *flag = (volatile int *)arg;
    *flag = 1;
}

void app_main() {
    esp_timer_handle_t my_timer;
    esp_timer_create_args_t timer_args = {
        .callback = timer_callback,
        .arg = (void *)&some_flag,
        .dispatch_method = ESP_TIMER_ISR, // 中断模式
        .name = "MyTimer"
    };

    esp_timer_create(&timer_args, &my_timer);
    esp_timer_start_once(my_timer, 1000000); // 1秒后触发
}

ESPTIMERISR:回调跑在中断里,超快。

IRAM_ATTR:函数放内存里,避免闪存延迟。

注意:中断里别干复杂活(比如 printf),否则崩。

4. 检查状态

想知道定时器跑没跑:

if (esp_timer_is_active(my_timer)) {
    printf("定时器还在跑\n");
}

和 FreeRTOS 定时器比比

FreeRTOS Timer(xTimer):

软件实现,依赖任务调度,精度受限(毫秒级)。

适合任务级别定时。

esp_timer:

硬件实现,微秒级精度,不受任务影响。

适合高精度或硬件相关场景(比如 PWM、传感器采样)。

需要掌握啥?

创建定时器: esptimercreate(),搞懂参数(回调、模式)。

启动定时器: startonce(单次)、startperiodic(周期),时间用微秒。

管理定时器: stop、delete,别忘了清理。

中断模式: ESPTIMERISR,简单回调放 IRAM。

实际场景: 比如每 100ms 采样 ADC、每秒闪灯。

总结

esp_timer 是 ESP32 的高精度定时器,靠硬件跑,准到微秒。

用法简单:创建 -> 启动(单次/周期) -> 回调。

比 FreeRTOS 定时器更硬核,适合嵌入式精确计时。

文档信息

版权声明:可自由转载(请注明转载出处)-非商用-非衍生

发表时间:2025年7月1日 11:26