ESP32有一组外设--定时器组。它可以选择不同的时钟源和分配系数。该定时器应用灵活,超时报警可以自动更新计数值。
typedefstruct {
gptimer_clock_source_tclk_src; /* 定时器时钟源,在clk_tree_defs.h中有个枚举soc_periph_gptimer_clk_src_t */
gptimer_count_direction_tdirection; /*计数方向 ,定义在timer_typers.h的枚举gptimer_count_direction_t中*/
uint32_tresolution_hz; /*频率分辨率,单位HZ,每个滴答步长是1/ resolution_hz秒*/
intintr_priority; /*定时器中断优先级,如果设置0,将分配优先级较低的中断*/
struct {
uint32_tintr_shared: 1; /*设置是否与其他外设共享此定时器终端号*/
} flags;
} gptimer_config_t;
esp_err_tgptimer_new_timer(
constgptimer_config_t*config,//填充完成的gptimer_config_t变量
gptimer_handle_t*ret_timer//返回的定时器句柄,所以在调用之前先要定义一个gptimer_handle_t变量,用于返回定时器句柄
)
esp_err_tgptimer_set_alarm_action(
gptimer_handle_ttimer, //上一步返回的定时器句柄
constgptimer_alarm_config_t*config//警报的相关配置
)
typedefstruct {
uint64_talarm_count; /*警报的目标计数值 */
uint64_treload_count; /*只有当auto_reload_on_alarm设置为ture,才会有影响,重载计数值 */
struct {
uint32_tauto_reload_on_alarm: 1; /*当警报发生时,重载按硬件开始 */
} flags;
} gptimer_alarm_config_t;
esp_err_tgptimer_register_event_callbacks(
gptimer_handle_ttimer, //返回的定时器句柄
constgptimer_event_callbacks_t*cbs, //事件回调函数
void*user_data//传递给回调函数的参数
)
//回调函数的函数原型,在gptimer_event_callbacks_t结构体里定义
typedefbool (*gptimer_alarm_cb_t)(gptimer_handle_ttimer, //定时器句柄
constgptimer_alarm_event_data_t*edata, //传递报警事件的相关数据
void*user_ctx//用户自定义参数
)
esp_err_tgptimer_enable(gptimer_handle_ttimer)
5.启动定时器
esp_err_tgptimer_start(gptimer_handle_ttimer)
/**
* Copyright (C) 2024-2034 HalfMoon2.
* All rights reserved.
*
* @file Filename without the absolute path
* @brief Brief description
* @author HalfMoon2
* @date 2025-06-13
* @version v0.1
*
* @revision history:
* 2025-06-13 - Initial version.
*/
#include <stdio.h>
#include <driver/gptimer.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_err.h>
#include <esp_log.h>
#define event_bit0 (1<<0)
EventGroupHandle_teventGroup=NULL;
boolgptimer_alarm_cb(gptimer_handle_ttimer,constgptimer_alarm_event_data_t*edata, void*user_ctx)
{
BaseType_tpxHigherPriorityTaskWoken;
xEventGroupSetBitsFromISR(eventGroup,event_bit0,&pxHigherPriorityTaskWoken);
returnfalse;
}
voidevent_task(void*pvParam)
{
while(1){
if(xEventGroupWaitBits(eventGroup,event_bit0,pdTRUE,pdFALSE,portMAX_DELAY)==1){
ESP_LOGI("gptimer","alarm success!!!");
}
}
}
staticvoidgptimer_init()
{
gptimer_handle_tgptimer=NULL;
gptimer_config_ttimer_config={
.clk_src=GPTIMER_CLK_SRC_DEFAULT,
.direction=GPTIMER_COUNT_UP,
.intr_priority=0,
.resolution_hz=1*1000*1000, //分辨率为1M,一次滴答1us
.flags.intr_shared=false
};
//创建定时器句柄
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
//设置警报动作,目标计数值,是否自动重载等
gptimer_alarm_config_talarm_config={
.alarm_count=1000000, //一次滴答1us,这里刚好1s
.reload_count=0,
.flags.auto_reload_on_alarm=true
};
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));
//注册警报事件
gptimer_event_callbacks_tcbs={
.on_alarm=gptimer_alarm_cb
};
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer,&cbs,NULL));
//使能定时器
ESP_ERROR_CHECK(gptimer_enable(gptimer));
//开启定时器
ESP_ERROR_CHECK(gptimer_start(gptimer));
}
voidapp_main(void)
{
//创建一个事件组
eventGroup=xEventGroupCreate();
gptimer_init();
xTaskCreatePinnedToCore(event_task,"event_task",2048,NULL,3,NULL,1);
}

从打印可以看出,刚好1秒触发一次警报。
gptimer_alarm_config_talarm_config= {
.alarm_count=edata->alarm_value+1000000, // 下一次警报在当前警报的基础上加 1s
};
// 更新警报值
gptimer_set_alarm_action(timer, &alarm_config);
作者: 二月半, 来源:面包板社区
链接: https://mbb.eet-china.com/blog/uid-me-1862109.html
版权声明:本文为博主原创,未经本人允许,禁止转载!
eeNick 2025-6-18 09:00