学习ESP32—高分辨率定时器(ESP Timer)使用指南
2026/6/25 21:34:01 网站建设 项目流程

ESP32 高分辨率定时器(ESP Timer)使用指南


目录

  • 1. ESP Timer 简介
  • 2. 头文件与依赖
  • 3. 定时器回调函数
  • 4. 定时器初始化与配置
  • 5. 启动定时器
  • 6. 完整使用示例
  • 7. 常用 API 参考
  • 8. 注意事项

1. ESP Timer 简介

ESP Timer 是 ESP-IDF 提供的高分辨率软件定时器 API。它具有以下特点:

  • 高精度:定时精度可达微秒级(μs)
  • 基于系统时钟:使用 64 位硬件计数器,不受 APB 频率变化影响
  • 灵活的回调机制:支持从任务或 ISR 上下文进入回调
  • 单次/周期模式:支持单次定时和周期性定时两种模式

适用场景

  • 精确延时控制
  • 周期性任务执行(如 LED 闪烁、传感器采样)
  • 超时检测
  • 需要微秒级精度的定时操作

2. 头文件与依赖

使用 ESP Timer 需要包含以下头文件:

#include"esp_timer.h"// ESP Timer API(核心)#include"esp_err.h"// 错误检查宏(可选,用于 ESP_ERROR_CHECK)

在自己的定时器模块头文件中声明:

#ifndef__ESPTIMER_H#define__ESPTIMER_H#include"esp_timer.h"/* 函数声明 */voidesptimer_init(uint64_ttps);/* 初始化高分辨率定时器 */#endif

注意:使用 ESP Timer 之前,通常需要初始化 NVS(非易失性存储),因为 ESP-IDF 系统组件可能依赖 NVS。


3. 定时器回调函数

定时器回调函数在定时时间到达时被自动调用。编写回调函数需遵循以下规范:

函数原型

voidesptimer_callback(void*arg);

参数说明

参数类型说明
argvoid *创建定时器时传入的用户参数,不需要时可设为NULL

代码示例

/** * @brief 定时器回调函数 * @param arg: 不携带参数 * @retval 无 */voidesptimer_callback(void*arg){LED0_TOGGLE();// 每到达定时周期,翻转一次 LED 状态}

回调函数注意事项

  • 回调函数应尽量简短,避免长时间阻塞
  • 不要在回调中使用会阻塞的 API(如等待信号量超过很短时间)
  • 回调执行时间应远小于定时周期

4. 定时器初始化与配置

4.1 配置结构体esp_timer_create_args_t

创建定时器前,需要先填充esp_timer_create_args_t结构体来配置定时器参数:

成员类型说明
.callbackesp_timer_cb_t定时到达时执行的回调函数指针
.argvoid *传递给回调函数的参数
.dispatch_methodesp_timer_dispatch_t回调执行方式
.nameconst char *定时器名称(用于调试和日志)
.skip_unhandled_eventsbool是否跳过未处理的事件(可选)

4.2dispatch_method取值

说明
ESP_TIMER_TASK回调由专用定时器任务执行(推荐,适合大多数场景)
ESP_TIMER_ISR回调在中断上下文中执行(延迟最低,但限制较多)

4.3 初始化函数实现

/** * @brief 初始化高分辨率定时器(ESP_TIMER) * @param tps: 定时器周期,以微秒为单位(μs) * 若以一秒为定时器周期来执行一次定时器中断,那此处 tps = 1s = 1000000μs * @retval 无 */voidesptimer_init(uint64_ttps){esp_timer_handle_tesp_tim_handle;/* 定义定时器句柄 *//* 定义一个定时器结构体设置定时器配置参数 */esp_timer_create_args_ttimer_arg={.callback=&esptimer_callback,/* 计时时间到达时执行的回调函数 */.arg=NULL,/* 传递给回调函数的参数 */.dispatch_method=ESP_TIMER_TASK,/* 进入回调方式,从定时器任务进入 */.name="Timer",/* 定时器名称 */};ESP_ERROR_CHECK(esp_timer_create(&timer_arg,&esp_tim_handle));/* 创建定时器 */ESP_ERROR_CHECK(esp_timer_start_periodic(esp_tim_handle,tps));/* 启动周期性定时器 */}

4.4 参数说明

参数说明
tps定时器触发周期,单位微秒(μs)。例如1000000表示 1 秒

5. 启动定时器

ESP Timer 提供两种启动方式:

5.1 启动周期性定时器

定时器以固定周期反复触发回调:

esp_err_tesp_timer_start_periodic(esp_timer_handle_ttimer,uint64_tperiod_us);
参数说明
timer定时器句柄
period_us定时周期,单位微秒(μs)
返回值ESP_OK成功;其他值表示失败

5.2 启动单次定时器

定时器仅触发一次回调后自动停止:

esp_err_tesp_timer_start_once(esp_timer_handle_ttimer,uint64_ttimeout_us);
参数说明
timer定时器句柄
timeout_us超时时间,单位微秒(μs)
返回值ESP_OK成功;其他值表示失败

5.3 停止与删除定时器

esp_err_tesp_timer_stop(esp_timer_handle_ttimer);/* 停止定时器 */esp_err_tesp_timer_delete(esp_timer_handle_ttimer);/* 删除定时器,释放资源 */

6. 完整使用示例

以下是一个完整的 ESP Timer 使用示例,实现 LED 每秒闪烁一次:

6.1 工程结构

05_esptimer/ ├── CMakeLists.txt ├── main/ │ ├── CMakeLists.txt │ └── main.c ├── components/ │ └── BSP/ │ ├── LED/ │ │ ├── led.h │ │ └── led.c │ └── ESPTIMER/ │ ├── esptimer.h │ └── esptimer.c └── README.md

6.2 main.c

#include"freertos/FreeRTOS.h"#include"freertos/task.h"#include"nvs_flash.h"#include<stdio.h>#include"led.h"#include"esptimer.h"/** * @brief 程序入口 * @param 无 * @retval 无 */voidapp_main(void){esp_err_tret;ret=nvs_flash_init();/* 初始化NVS */if(ret==ESP_ERR_NVS_NO_FREE_PAGES||ret==ESP_ERR_NVS_NEW_VERSION_FOUND){ESP_ERROR_CHECK(nvs_flash_erase());ESP_ERROR_CHECK(nvs_flash_init());}led_init();/* 初始化LED */esptimer_init(1000000);/* 初始化ESP_TIMER,周期1秒(1000000μs)*/while(1){vTaskDelay(pdMS_TO_TICKS(10));/* 延时10ms */}}

6.3 实验现象

程序运行后,LED0 每隔1 秒翻转一次电平状态,即 LED 以 2 秒为周期闪烁。


7. 常用 API 参考

7.1 定时器生命周期 API

API功能
esp_timer_create()创建定时器
esp_timer_start_once()启动单次定时器
esp_timer_start_periodic()启动周期性定时器
esp_timer_restart()重新启动已启动的定时器(更新超时时间)
esp_timer_stop()停止定时器
esp_timer_delete()删除定时器

7.2 时间获取 API

API功能
esp_timer_get_time()获取自启动以来的时间(微秒,64位)
esp_timer_dump()打印所有定时器的状态信息(调试用)

7.3 系统初始化 API

API功能
esp_timer_init()初始化 ESP Timer 子系统(在调用esp_timer_create前自动调用)
esp_timer_deinit()反初始化 ESP Timer 子系统

8. 注意事项

8.1 回调上下文选择

上下文优点限制
ESP_TIMER_TASK可调用大部分 FreeRTOS API,实现灵活延迟稍高(取决于任务优先级)
ESP_TIMER_ISR延迟极低不能调用阻塞 API,不能使用 printf 打印浮点数等

一般应用场景推荐使用ESP_TIMER_TASK

8.2 精度与周期

  • 最小定时周期取决于系统负载和回调执行时间,理论上可达微秒级
  • 定时周期不宜过短(如几微秒),否则回调可能来不及执行
  • 1 秒 = 1,000,000 微秒(μs)

8.3 资源管理

  • 不再使用的定时器应及时调用esp_timer_delete()删除,释放内存
  • 一个定时器同一时刻只能启动一次,如需更改周期,先停止再重新启动
  • 使用ESP_ERROR_CHECK宏检查 API 返回值,便于调试

8.4 NVS 初始化

ESP Timer 的某些依赖(如日志、系统时间等)需要 NVS 支持,建议在app_main中首先初始化 NVS:

esp_err_tret=nvs_flash_init();if(ret==ESP_ERR_NVS_NO_FREE_PAGES||ret==ESP_ERR_NVS_NEW_VERSION_FOUND){ESP_ERROR_CHECK(nvs_flash_erase());ESP_ERROR_CHECK(nvs_flash_init());}

8.5 与 FreeRTOS 软件定时器的区别

特性ESP TimerFreeRTOS 软件定时器
精度微秒级毫秒级(受 tick 频率限制)
基于硬件 64 位计数器FreeRTOS tick 计数
使用复杂度简单,API 直观需要配置定时器任务
适用场景高精度定时低精度周期性任务

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询