系列文章目录

持续更新…



前言

在嵌入式开发中,定时器是实现精确控制和任务调度的关键组件。ESP32 作为一款功能强大的微控制器,内建了多个高精度的硬件定时器,广泛应用于定时任务、周期性中断、PWM 输出、看门狗监控等场景。

本篇文章将深入介绍 ESP32 的定时器模块,涵盖其硬件架构、功能特性、配置方法以及实际应用示例。我们将重点讲解如何利用 ESP32 的 64 位定时器实现精确的时间控制,并通过中断机制响应特定事件。

参考文档:ESP32-S3技术参考手册ESP32-S3编程指南


一、定时器概述

ESP32 提供了强大的硬件定时器功能,能够为嵌入式系统提供精准的定时控制。ESP32 内置了 4 个 64 位通用定时器,分为 2 组,每组包含 2 个定时器。每个定时器都包括一个 16 位的时钟预分频器和一个 64 位的时基计数器。定时器可用于设定时间间隔、触发中断、产生报警等功能,广泛应用于定时任务、周期性任务等。
在这里插入图片描述

定时器组结构
ESP32 定时器分为两个定时器组:定时器组 0(TIMERG0)和定时器组 1(TIMERG1)。每个定时器组内包含两个通用定时器,分别标识为 TIMGn_Tx,其中 n 表示定时器组编号(0 或 1),x 表示定时器编号(0 或 1)。定时器可用于多种任务,包括精确时间控制、周期性报警、中断触发等。

在这里插入图片描述
定时器特性:
1.16 位预分频器:能够对时钟源进行 2 到 65536 之间的分频。
2.64 位时基计数器:可配置为向上计数或向下计数,支持高精度定时。
3.自动重载:定时器可以在触发报警时自动重新加载初始值。
4.报警功能:定时器可以在当前计数值达到报警值时触发报警,支持定时中断。
5.软件控制:可以通过软件即时重新加载计数器的值。
6.中断支持:支持电平触发中断和边沿触发中断,适合用于定时任务管理。

每个定时器的工作原理包括以下几个部分:

1.16位预分频器

定时器的预分频器用于将输入的时钟信号进行分频,以产生适合的时基时钟(TB_CLK)供时基计数器使用。ESP32 的定时器支持配置分频系数,范围从 2 到 65536,可以对 APB 时钟(通常为 80 MHz)进行灵活的分频。

预分频器配置:通过寄存器 TIMG_Tx_DIVIDER 配置分频系数。当配置为 0 时,分频系数为 65536;当配置为 1 时,分频系数为 2。

2.64位时基计数器

定时器的时基计数器基于 TB_CLK,可以配置为向上计数或向下计数。定时器计数器的值可以通过软件读取,也可以配置为在特定条件下触发报警。

计数器配置:可以通过寄存器 TIMG_Tx_INCREASE 来控制计数器的增减方向(向上或向下)。定时器计数器达到预设的报警值时,会触发报警或中断。

读取计数器值:由于计数器为 64 位,CPU 只能以两个 32 位的值来读取计数器的高低位。读取操作需要通过寄存器 TIMG_TxUPDATE_REG 来锁存计数器值。

ESP32 系列芯片的时基计数器位宽因型号而异,其中 ESP32 为 64 位,ESP32-S3 为 54 位。请查阅相应型号的技术参考手册以获取详细信息。

3.报警产生

定时器支持报警功能,可以在计数器值达到某个报警值时触发报警。报警值分别通过寄存器 TIMG_TxALARMLO_REG 和 TIMG_TxALARMHI_REG 进行设置。

报警触发:报警会在定时器计数器值等于报警值时触发。为了避免“报警使能过晚”而错过触发,定时器支持在计数器值高于报警值(向上计数器)或低于报警值(向下计数器)时立即触发报警。

报警自动重新加载:报警触发后,可以通过寄存器 TIMG_Tx_AUTORELOAD 启用自动重新加载功能,从而使计数器在报警后重新加载初始值,继续计数。

4.中断

定时器可以触发中断来通知 CPU 执行特定任务。ESP32 支持电平触发中断和边沿触发中断,可以用于周期性任务和精确时间控制。

中断控制:通过 TIMG_Tx_INT_ENA 寄存器使能定时器中断,触发后会通过 TIMG_Tx_INT_RAW 和 TIMG_Tx_INT_ST 寄存器反映中断状态。

清除中断:可以通过 TIMG_Tx_INT_CLR 寄存器清除定时器中断,确保在下一个中断发生之前清除先前的中断状态。

二、定时器类型定义及相关API

在 ESP32 中,存在两种定时器 API:一种是传统的硬件定时器(Hardware Timer),另一种是通用定时器在 ESP32 平台上,底层硬件资源都是同一套“定时器组(Timer Group / TIMG)”——两组定时器(TIMG0/TIMG1),每组各含两个通用硬件定时器;经典 ESP32 的通用定时器为 64 位计数器 + 16 位预分频器(详见 TRM),驱动层则提供了两套 API:

早期提供的 Timer Group 驱动(driver/timer.h):直接面向 TIMG 外设的“旧式”接口;
自 IDF 4.4 起引入并在 5.x 里主推的 GPTimer 驱动(driver/gptimer.h):更现代的“新式”通用定时器抽象。

GPTimer 新驱动,功能更全、更易用:支持更灵活的时钟源与分辨率、报警(自动重装载)、ISR 回调、(按需)获取电源管理锁,且能与 ETM/clock tree 更好集成,适合新项目与后续维护。

Timer Group API 旧驱动:直接操作 TIMG 外设,API 粒度偏底层,官方已给出迁移到 GPTimer的指引;更适合维护老代码或确实要与旧示例保持一致时使用。

ESP32定时器类型定义

//=============================================================================
// ESP32/ESP32-S3 定时器类型总览(仅类型定义,无函数)
// - Part A: 旧版 Timer Group(driver/timer.h → driver/timer_types_legacy.h)
// - Part B: 新版 GPTimer(driver/gptimer.h → driver/gptimer_types.h / hal/timer_types.h)
//=============================================================================
#include <stdint.h>
#include <stdbool.h>

//=============================================================================
// Part A) 旧版 Timer Group(LEGACY)类型定义
//   说明:适配 driver/timer.h;在 IDF v5.x 中标记为 deprecated,建议迁移 GPTimer。
//=============================================================================

// 1) 定时器组
typedef enum {
    TIMER_GROUP_0 = 0,   // 组 0(TIMERG0)
    TIMER_GROUP_1 = 1,   // 组 1(TIMERG1)
    TIMER_GROUP_MAX
} timer_group_t;

// 2) 组内定时器索引
typedef enum {
    TIMER_0 = 0,         // 每组定时器 0
    TIMER_1 = 1,         // 每组定时器 1
    TIMER_MAX
} timer_idx_t;

// 3) 计数方向
typedef enum {
    TIMER_COUNT_UP   = 0,  // 向上计数
    TIMER_COUNT_DOWN = 1,  // 向下计数
    TIMER_COUNT_MAX
} timer_count_dir_t;

// 4) 启停控制(用于立即启动/暂停)
typedef enum {
    TIMER_START = 0,     // 使能计数
    TIMER_PAUSE = 1,     // 暂停计数
    TIMER_START_MAX
} timer_start_t;

// 5) 报警使能
typedef enum {
    TIMER_ALARM_DIS = 0, // 禁用报警
    TIMER_ALARM_EN  = 1, // 使能报警
    TIMER_ALARM_MAX
} timer_alarm_t;

// 6) 中断触发模式
typedef enum {
    TIMER_INTR_LEVEL = 0, // 电平触发
    TIMER_INTR_EDGE  = 1, // 边沿触发
    TIMER_INTR_MAX
} timer_intr_mode_t;

// 7) 自动重载
typedef enum {
    TIMER_AUTORELOAD_DIS = 0, // 报警后不自动重装载
    TIMER_AUTORELOAD_EN  = 1, // 报警后自动重装载
    TIMER_AUTORELOAD_MAX
} timer_autoreload_t;

// 8) 组中断位掩码(用于 group 级别开关中断)
typedef enum {
    TIMER_INTR_T0  = 1 << 0,  // 组内定时器0中断
    TIMER_INTR_T1  = 1 << 1,  // 组内定时器1中断
    TIMER_INTR_WDT = 1 << 2,  // 主看门狗中断(属于定时器组模块)
} timer_intr_t;

// 9) 定时器 ISR 回调原型与句柄(LEGACY 回调接口)
typedef bool (*timer_isr_t)(void *arg); // 返回 true 表示在 ISR 末尾需要执行一次 YIELD
typedef void *timer_isr_handle_t;       // 中断句柄

// 10) 旧版定时器配置结构体
typedef struct {
    uint32_t            divider;      // 预分频:2~65536(0→65536,1/2→2)
    timer_count_dir_t   counter_dir;  // 计数方向(上/下)
    timer_start_t       counter_en;   // 上电后计数器启/停
    timer_alarm_t       alarm_en;     // 报警使能
    timer_intr_mode_t   intr_type;    // 中断类型(电平/边沿)
    timer_autoreload_t  auto_reload;  // 自动重载
    // 说明:老驱动默认使用 APB 时钟;不同芯片/版本可能还有扩展字段,请以目标版本头文件为准
} timer_config_t;

//=============================================================================
// Part B) 新版 GPTimer 类型定义
//   说明:适配 driver/gptimer.h & driver/gptimer_types.h
//=============================================================================

// 1) 计数方向(新版)
typedef enum {
    GPTIMER_COUNT_DOWN = 0, // 向下计数
    GPTIMER_COUNT_UP   = 1, // 向上计数
} gptimer_count_direction_t;

// 2) 定时器时钟源(别名到 SoC 专用枚举)
//    注:不同芯片的可选值不同(如 APB、XTAL、RC_FAST 等),请查 soc_periph_gptimer_clk_src_t
typedef soc_periph_gptimer_clk_src_t gptimer_clock_source_t;

// 3) GPTimer 句柄与回调原型
typedef struct gptimer_t *gptimer_handle_t;  // 定时器句柄类型
typedef struct {
    uint64_t count_value;  // 当前计数值(捕获时刻)
    uint64_t alarm_value;  // 当前报警比较值
} gptimer_alarm_event_data_t;                // 报警事件数据(ISR 环境可读)
typedef bool (*gptimer_alarm_cb_t)(gptimer_handle_t timer,
                                   const gptimer_alarm_event_data_t *edata,
                                   void *user_ctx); // 报警回调;返回 true 可唤醒高优任务

// 4) 事件回调集合(目前仅报警回调)
typedef struct {
    gptimer_alarm_cb_t on_alarm; // 报警回调(ISR 环境执行)
} gptimer_event_callbacks_t;

// 5) GPTimer 基本配置
typedef struct {
    gptimer_clock_source_t     clk_src;        // 时钟源(SoC 相关)
    gptimer_count_direction_t  direction;      // 计数方向
    uint32_t                   resolution_hz;  // 计数分辨率 Hz(1 tick = 1/resolution_hz 秒)
    int                        intr_priority;  // 中断优先级(0→由驱动选择较低优先级 1/2/3)
    struct {
        uint32_t intr_shared : 1;              // 允许与其他外设共享中断号
    } flags;
} gptimer_config_t;

// 6) 报警配置
typedef struct {
    uint64_t alarm_count;   // 报警触发计数值(比较值)
    uint64_t reload_count;  // 自动重装载的重载值(仅当 auto_reload_on_alarm=1 生效)
    struct {
        uint32_t auto_reload_on_alarm : 1; // 报警发生时由硬件立即重装载
    } flags;
} gptimer_alarm_config_t;

ESP32定时器相关API

//=============================================================================
// ESP32 定时器相关函数总表(GPTimer / Legacy Timer Group / esp_timer)
// 依据 ESP-IDF 官方头文件与文档梳理(v5.x 系列)。
// 说明:仅列出公开 API 原型与简要注释;名称以官方为准,无臆造函数。
//=============================================================================

#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"

//=============================================================================
// 一、通用硬件定时器 GPTimer(新版驱动:driver/gptimer.h)
//=============================================================================

// 创建 GPTimer 并返回句柄(新建后处于 "init" 态)
esp_err_t gptimer_new_timer(
    const gptimer_config_t *config,   // [in] 定时器配置
    gptimer_handle_t *ret_timer       // [out] 返回定时器句柄
);

// 删除 GPTimer 句柄(需在 "init" 态)
esp_err_t gptimer_del_timer(
    gptimer_handle_t timer            // [in] 定时器句柄
);

// 设置原始计数值(可在 ISR 中调用;对运行中定时器立即生效)
esp_err_t gptimer_set_raw_count(
    gptimer_handle_t timer,           // [in]
    uint64_t value                    // [in] 计数值
);

// 读取原始计数值(会触发一次软件捕获;可在 ISR 中调用)
esp_err_t gptimer_get_raw_count(
    gptimer_handle_t timer,           // [in]
    uint64_t *value                   // [out] 当前计数
);

// 读取“实际分辨率”(Hz),用于把 count 换算为秒
esp_err_t gptimer_get_resolution(
    gptimer_handle_t timer,           // [in]
    uint32_t *out_resolution          // [out] 实际分辨率(Hz)
);

// 读取最近一次“捕获”值(不触发捕获;可在 ISR 中调用)
esp_err_t gptimer_get_captured_count(
    gptimer_handle_t timer,           // [in]
    uint64_t *value                   // [out] 捕获计数值
);

// 注册事件回调(如报警回调);首次调用需在 enable 之前
esp_err_t gptimer_register_event_callbacks(
    gptimer_handle_t timer,                           // [in]
    const gptimer_event_callbacks_t *cbs,             // [in] 回调集合(只包含 on_alarm)
    void *user_data                                   // [in] 透传给回调的用户数据
);

// 设置报警行为(目标值、是否自动重载、重载值;传 NULL 可关闭报警)
esp_err_t gptimer_set_alarm_action(
    gptimer_handle_t timer,                           // [in]
    const gptimer_alarm_config_t *config              // [in] 报警配置(或 NULL 关闭)
);

// 使能 GPTimer(状态从 init -> enable;也会安装中断等)
esp_err_t gptimer_enable(gptimer_handle_t timer);

// 禁用 GPTimer(状态从 enable -> init;卸载中断、释放电源管理锁)
esp_err_t gptimer_disable(gptimer_handle_t timer);

// 启动 GPTimer 计数(状态从 enable -> run;可在 ISR 中调用)
esp_err_t gptimer_start(gptimer_handle_t timer);

// 停止 GPTimer 计数(状态从 run -> enable;可在 ISR 中调用)
esp_err_t gptimer_stop(gptimer_handle_t timer);

//=============================================================================
// 二、硬件定时器(旧版 Timer Group 驱动:driver/timer.h)
// 说明:此驱动已标注“deprecated”,官方建议迁移到 GPTimer。
//=============================================================================

// 读当前计数值(64-bit)
esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *timer_val);

// 以秒为单位读取计数值(double)
esp_err_t timer_get_counter_time_sec(timer_group_t group_num, timer_idx_t timer_num, double *time);

// 写计数器当前值
esp_err_t timer_set_counter_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t load_val);

// 启动/暂停计数器
esp_err_t timer_start(timer_group_t group_num, timer_idx_t timer_num);
esp_err_t timer_pause(timer_group_t group_num, timer_idx_t timer_num);

// 设置计数方向(向上/向下)
esp_err_t timer_set_counter_mode(timer_group_t group_num, timer_idx_t timer_num, timer_count_dir_t counter_dir);

// 报警时是否自动重载
esp_err_t timer_set_auto_reload(timer_group_t group_num, timer_idx_t timer_num, timer_autoreload_t reload);

// 设置分频(2~65536)
esp_err_t timer_set_divider(timer_group_t group_num, timer_idx_t timer_num, uint32_t divider);

// 设置/获取报警阈值(64-bit)
esp_err_t timer_set_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_value);
esp_err_t timer_get_alarm_value(timer_group_t group_num, timer_idx_t timer_num, uint64_t *alarm_value);

// 使能/禁用报警功能
esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_alarm_t alarm_en);

// 以“回调”方式添加/移除 ISR(由驱动代为处理状态位)
esp_err_t timer_isr_callback_add(timer_group_t group_num, timer_idx_t timer_num, timer_isr_t isr_handler, void *arg, int intr_alloc_flags);
esp_err_t timer_isr_callback_remove(timer_group_t group_num, timer_idx_t timer_num);

// 直接注册完整 ISR(自行处理寄存器与自旋锁等)
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num, void (*fn)(void *), void *arg, int intr_alloc_flags, timer_isr_handle_t *handle);

// 初始化/反初始化
esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer_config_t *config);
esp_err_t timer_deinit(timer_group_t group_num, timer_idx_t timer_num);

// 读取当前配置
esp_err_t timer_get_config(timer_group_t group_num, timer_idx_t timer_num, timer_config_t *config);

// 组级中断屏蔽控制(启用/禁用)
esp_err_t timer_group_intr_enable(timer_group_t group_num, timer_intr_t intr_mask);
esp_err_t timer_group_intr_disable(timer_group_t group_num, timer_intr_t intr_mask);

// 单个定时器中断使能/禁用
esp_err_t timer_enable_intr(timer_group_t group_num, timer_idx_t timer_num);
esp_err_t timer_disable_intr(timer_group_t group_num, timer_idx_t timer_num);

// —— 下列为“仅可在 ISR 中调用”的便捷函数 ——
// 清中断状态 / 重新使能报警
void     timer_group_clr_intr_status_in_isr(timer_group_t group_num, timer_idx_t timer_num);
void     timer_group_enable_alarm_in_isr(timer_group_t group_num, timer_idx_t timer_num);

// ISR 中读计数 / 改报警阈值 / 控制定时器使能
uint64_t timer_group_get_counter_value_in_isr(timer_group_t group_num, timer_idx_t timer_num);
void     timer_group_set_alarm_value_in_isr(timer_group_t group_num, timer_idx_t timer_num, uint64_t alarm_val);
void     timer_group_set_counter_enable_in_isr(timer_group_t group_num, timer_idx_t timer_num, timer_start_t counter_en);

// ISR 中读取组中断状态 / 读取自动重载使能状态
uint32_t timer_group_get_intr_status_in_isr(timer_group_t group_num);
bool     timer_group_get_auto_reload_in_isr(timer_group_t group_num, timer_idx_t timer_num);

//=============================================================================
// 三、ESP 高分辨率软件定时器(esp_timer.h)
// 说明:基于 64-bit 微秒计时,运行在系统软件层,非 Timer Group 硬件资源。
//=============================================================================

// 早期初始化 / 初始化 / 反初始化(多用于系统层或特殊场合)
void     esp_timer_early_init(void);
esp_err_t esp_timer_init(void);
esp_err_t esp_timer_deinit(void);

// 创建 / 删除定时器
esp_err_t esp_timer_create(const esp_timer_create_args_t *args, esp_timer_handle_t *out_handle);
esp_err_t esp_timer_delete(esp_timer_handle_t timer);

// 启动一次性 / 周期性定时器;重启(修改超时/周期)
esp_err_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us);
esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period_us);
esp_err_t esp_timer_restart(esp_timer_handle_t timer, uint64_t timeout_or_period_us);

// 停止 / 查询活动状态
esp_err_t esp_timer_stop(esp_timer_handle_t timer);
bool      esp_timer_is_active(esp_timer_handle_t timer);

// 读取当前时间(自启动以来的微秒数)
int64_t   esp_timer_get_time(void);

// 调试输出当前定时器状态(到给定流,如 stdout)
esp_err_t esp_timer_dump(FILE *stream);

// 从 ISR 回调中请求调度切换(用于高优任务唤醒)
void      esp_timer_isr_dispatch_need_yield(void);

// 读取下次唤醒点(微秒)—— 供电源管理/睡眠流程使用
int64_t   esp_timer_get_next_alarm(void);
int64_t   esp_timer_get_next_alarm_for_wake_up(void);

// 查询周期或到期时间(若适用)
esp_err_t esp_timer_get_period(esp_timer_handle_t timer, uint64_t *period_us);
esp_err_t esp_timer_get_expiry_time(esp_timer_handle_t timer, uint64_t *expiry_us);

// ETM 集成:导出 “esp_timer 报警事件” 供 ETM 连接其他外设
esp_err_t esp_timer_new_etm_alarm_event(esp_etm_event_handle_t *out_event);

三、定时器示例程序

基于ESP32-S3:
1秒周期自动重载中断示例

#include <stdio.h>
#include "driver/gptimer.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

static const char *TAG = "GPTIMER";

bool on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *event_data, void *user_data)  
{
    ESP_EARLY_LOGI(TAG, "Alarm triggered!\n"); // 打印报警信息
    return false; // 通常返回 false
}

void app_main(void)
{
    // 1) 新建定时器(1 MHz 分辨率:1 tick = 1 us)
    gptimer_handle_t timer = NULL;
    gptimer_config_t cfg = {
        .clk_src = GPTIMER_CLK_SRC_APB,   // 默认 APB 时钟
        .direction = GPTIMER_COUNT_UP,    // 向上计数
        .resolution_hz = 1 * 1000 * 1000, // 1 MHz -> 1us/tick
        .intr_priority = 1,               // 中断优先级(1/2/3 越小越低)
    };
    ESP_ERROR_CHECK(gptimer_new_timer(&cfg, &timer));

    // 2) 注册中断回调
    gptimer_event_callbacks_t cbs = {
        .on_alarm = on_alarm_cb,
    };
    ESP_ERROR_CHECK(gptimer_register_event_callbacks(timer, &cbs, NULL));

    // 3) 启用定时器(进入 enable 状态)
    ESP_ERROR_CHECK(gptimer_enable(timer));

    // 4) 配置报警动作:1秒触发一次,并硬件自动重装
    //    由于分辨率 1 MHz,1 Hz 周期 = 1,000,000 tick
    gptimer_alarm_config_t alarm_cfg = {
        .alarm_count = 1 * 1000 * 1000ULL, // 到达该计数值产生报警
        .reload_count = 0,                 // 报警后从 0 重新计数
        .flags.auto_reload_on_alarm = 1,      // 自动重装(周期模式)
    };
    ESP_ERROR_CHECK(gptimer_set_alarm_action(timer, &alarm_cfg));

    // 5) 启动计数(进入 run 状态)
    ESP_ERROR_CHECK(gptimer_start(timer));
    ESP_LOGI(TAG, "Timer started.");

    while (1)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }

}

1 秒周期自动重载中断(累计 5 秒后停止并重启系统)示例

#include <stdio.h>
#include "driver/gptimer.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"

static const char *TAG = "GPTIMER";

bool IRAM_ATTR on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *event_data, void *user_data)
{
    static uint32_t count = 0;
    count++;
    ESP_EARLY_LOGI(TAG, "Time: %d s", count);
    if (count >= 5)
    {
        ESP_EARLY_LOGI(TAG, "Stopping timer");
        gptimer_stop(timer); 
        gptimer_del_timer(timer); 
        count = 0;
        ESP_EARLY_LOGI(TAG, "System restarting...");
        esp_restart(); // 重启系统
    }
    return false;
}

void app_main(void)
{
    // 1) 创建定时器:1 MHz 分辨率(1 tick = 1 us)
    gptimer_handle_t tmr = NULL;
    gptimer_config_t cfg = {
        .clk_src = GPTIMER_CLK_SRC_DEFAULT,
        .direction = GPTIMER_COUNT_UP,
        .resolution_hz = 1 * 1000 * 1000, // 1 MHz
    };
    ESP_ERROR_CHECK(gptimer_new_timer(&cfg, &tmr));

    // 2) 配置回调(先注册,再 enable)
    gptimer_event_callbacks_t cbs = {
        .on_alarm = on_alarm_cb,
    };
    ESP_ERROR_CHECK(gptimer_register_event_callbacks(tmr, &cbs, NULL));

    // 3) 配置报警:每 1_000_000 tick 触发(即 1 s),自动重装载
    gptimer_alarm_config_t alarm = {
        .reload_count = 0,
        .alarm_count = 1 * 1000 * 1000,     // 1 s @ 1 MHz
        .flags.auto_reload_on_alarm = true, // 周期模式
    };
    ESP_ERROR_CHECK(gptimer_set_alarm_action(tmr, &alarm));

    // 4) 启动定时器
    ESP_ERROR_CHECK(gptimer_enable(tmr));
    ESP_ERROR_CHECK(gptimer_start(tmr));
    ESP_LOGI(TAG, "1 Hz timer started");

    while (1)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}


总结

本文系统梳理了 ESP32 的定时器子系统,涵盖硬件结构(两组四个 64 位 通用定时器、16 位预分频)、报警与中断机制、以及 GPTimer 新驱动 与 Timer Group 旧驱动 的核心用法。通过示例展示了 1 Hz 周期报警及回调处理流程,并给出回调最小化与任务化处理的实践建议。结合合适的时钟源与分辨率配置、自动重装载和中断回调,开发者可以在低开销前提下实现精确、可靠的定时任务与事件调度,适配从简单周期任务到更复杂的实时控制场景。希望本文能帮助你在实际项目中快速落地与优化基于 ESP32 的定时与调度。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐