【ESP32 IDF】ESPTIMER定时器
文章目录
- 前言
- 一、ESPTIMER定时器的介绍
- 1.1 定时器是什么
- 1.2 ESPTIMER定时器的介绍
- 二、ESPTIMER的使用
- 2.1 简单使用过程
- 2.2 停止定时器
- 2.3 删除定时器
- 三、示例代码
- 总结
前言
在ESP32 IDF开发框架中,ESPTIMER是一个功能强大的定时器模块,用于实现定时任务和周期性操作。ESPTIMER可以帮助开发者按照预定的时间间隔执行特定的代码,从而实现定时触发、周期性任务、延时执行等功能。本文将介绍ESPTIMER的基本用法和一些常见的应用场景。
一、ESPTIMER定时器的介绍
1.1 定时器是什么
单片机(Microcontroller)中的定时器是一种硬件模块,用于计时、计数和生成定时事件。定时器通常由一个或多个计时/计数器组成,并且具有相关的控制逻辑和寄存器。它是单片机中的重要组件,广泛应用于各种实时计时、时间测量和定时操作的应用中。
定时器在单片机中的作用包括:
事件计时:定时器可以用于测量两个事件之间的时间间隔。开发者可以使用定时器来计算传感器读数之间的时间间隔、测量电平持续时间或定时特定操作的执行时间。
周期性操作:定时器可以配置为以固定的时间间隔生成中断或触发相关事件。这种周期性操作对于周期性数据采集、控制信号的生成和实时任务的调度非常有用。
脉冲宽度调制(PWM):定时器通常可以生成PWM信号,用于控制模拟电路、执行数字-模拟转换或驱动电机等设备。通过调整定时器的计数值和输出设置,可以实现不同占空比的PWM信号。
超时检测:使用定时器可以实现超时检测功能,以便在特定时间内接收或处理输入数据。例如,通过设定定时器的计数值和预定时间,可以检测输入信号是否在指定时间内到达。
时基生成:定时器可以用于生成时基信号,例如时钟信号或其他时间参考信号,用于同步其他硬件模块的操作。
定时器在单片机中的具体实现和功能会根据芯片架构和制造商的不同而有所差异。每个单片机都会提供特定的定时器模块,并且通常包括计数器、预分频器、控制寄存器和中断机制等。开发者可以通过配置和操作这些寄存器来实现所需的定时功能。
总的来说,单片机中的定时器是一种硬件模块,用于计时、计数和生成定时事件。它在实时计时、时间测量、周期性操作和时基生成等应用中发挥着重要作用。开发者可以利用定时器来满足各种特定的计时和定时需求,从而实现单片机系统的功能扩展和更高级的应用。
1.2 ESPTIMER定时器的介绍
SPTIMER是Espressif Systems提供的定时器功能库,集成在ESP32 IDF(IoT Development Framework)中。它为开发者提供了一种简单而强大的方式来实现定时任务和周期性操作。
ESPTIMER特点如下:
精确的定时控制:ESPTIMER通过使用硬件定时器,可以以微秒级的精度进行定时,非常适用于对时间精度有较高要求的应用场景。
多任务支持:ESPTIMER可以同时管理多个定时器任务,每个任务可以独立运行,互不干扰。这意味着可以用一个单独的定时器来处理多个不同的任务。
灵活的任务调度:ESPTIMER提供了丰富的任务调度选项,包括在指定时间触发、循环执行、延时执行等。开发者可以根据自己的需求,轻松地配置定时器按照预定的时间间隔执行代码。
多种工作模式:ESPTIMER支持多种工作模式,包括单次定时器、重复定时器和高精度定时器。单次定时器在触发后只会执行一次任务,重复定时器会按照设置的时间间隔周期性执行任务,高精度定时器提供了更高的时间精度。
在idf中,除了ESPTIMER软件定时器外,还有GPTIMER定时器,他们的区别如下:
在ESP32 IDF(IoT Development Framework)中,ESPTIMER和GPTIMER是用于处理定时器功能的不同组件。
ESPTIMER(ESP32 Timer):ESPTIMER是ESP32 IDF框架提供的软件定时器组件。它是基于硬件定时器实现的,但由ESP32的系统时钟(80 MHz)驱动,并通过软件进行计数和处理。ESPTIMER可用于创建和管理多个定时器实例,并执行定时操作,如定时任务、定时中断等。
GPTIMER(General Purpose Timer):GPTIMER是ESP32的硬件定时器组件。ESP32芯片上具有多个GPTIMER,每个GPTIMER都有自己的配置寄存器和计数器。GPTIMER是与ESP32的硬件平台紧密相关的,可以执行各种基于时间的操作,如生成精确的定时触发信号、捕获外部事件、产生PWM信号等。
区别:
实现方式:ESPTIMER是基于ESP32系统时钟的软件实现,而GPTIMER是硬件定时器组件。
灵活性:ESPTIMER提供了更多的灵活性和可配置性,允许开发者根据需要创建和管理多个定时器实例。而GPTIMER是固定的硬件定时
二、ESPTIMER的使用
2.1 简单使用过程
对于IDF的ESPTIMER定时器我们需要进行下面这些步骤:
- 定义定时器句柄
定时器句柄的类型为:esp_timer_handle_t
我们可以这样定义对应的句柄变量:esp_timer_handle_t esp_tim_handle;
- 定义定时器结构体
定时器结构体的类型为:esp_timer_create_args_t
他的定义如下:
typedef struct {
esp_timer_cb_t callback; //!< Function to call when timer expires
void* arg; //!< Argument to pass to the callback
esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR
const char* name; //!< Timer name, used in esp_timer_dump function
bool skip_unhandled_events; //!< Skip unhandled events for periodic timers
} esp_timer_create_args_t;
esp_timer_cb_t callback: 这是一个函数指针,用于指定定时器触发时要调用的回调函数。当定时器到达设定的时间后,系统将调用此回调函数执行相应的任务。
void* arg
: 这是一个指针,用于传递给回调函数的参数。您可以将任何类型的数据结构转换为void*指针,并在回调函数中进行类型转换和使用。
esp_timer_dispatch_t dispatch_method
: 这是一个枚举类型的成员,用于指定回调函数是从任务(task)还是中断服务函数(ISR)中调用。它可以采用以下两个值:
ESP_TIMER_TASK
: 表示从任务中调用回调函数(默认值)。
ESP_TIMER_ISR
: 表示从中断服务函数中调用回调函数。
const char* name
: 这是一个指向字符数组的指针,用于为定时器指定一个名称。该名称在调试和跟踪定时器时非常有用,例如在调用esp_timer_dump()
函数时使用。
bool skip_unhandled_events
: 这是一个布尔类型的标志,用于控制是否跳过未处理的事件(仅适用于周期性定时器)。如果设置为true,周期性定时器在前一个定时器事件未处理之前将不会生成后续事件。如果设置为false,则每个定时器事件都将生成一个新的事件,即使前一个事件尚未处理。
- 创建一个事件
我们可以使用下面这个函数创建一个事件:
esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args,
esp_timer_handle_t* out_handle);
参数1为定时器结构体的指针,参数2为定时器句柄
- 开启定时器,并设置回调调用的时间
我们可以使用下面这个函数开启定时器并且指定回调函数调用的时间:
他的时间单位为us
esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period);
2.2 停止定时器
我们可以使用下面这个函数停止指定定时器,参数为定时器的句柄:
esp_err_t esp_timer_stop(esp_timer_handle_t timer);
2.3 删除定时器
我们可以使用下面这个函数删除指定的定时器:
参数为定时器的句柄
esp_err_t esp_timer_delete(esp_timer_handle_t timer);
三、示例代码
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_timer.h"
// 定时器回调函数,每秒打印一次消息
void timer_callback(void* arg)
{
printf("Timer expired\n");
}
void app_main()
{
// 创建一个esp_timer_create_args_t结构体,设置定时器参数
esp_timer_create_args_t timer_args = {
.callback = timer_callback, // 设置回调函数
.name = "my_timer", // 设置定时器名称
.dispatch_method = ESP_TIMER_TASK, // 从任务中调用回调函数
.skip_unhandled_events = false // 不跳过未处理的事件
};
// 创建定时器
esp_timer_handle_t timer;
esp_timer_create(&timer_args, &timer);
// 启动定时器,每秒触发一次
esp_timer_start_periodic(timer, 1000000); // 1000000微秒 = 1秒
// 等待10秒钟
vTaskDelay(10000 / portTICK_PERIOD_MS); // 等待10秒
// 停止定时器
esp_timer_stop(timer);
// 删除定时器
esp_timer_delete(timer);
// 任务结束
vTaskDelete(NULL);
}
总结
ESPTIMER是ESP32 IDF开发框架中提供的定时器模块,具有以下特点和优势:
精确的定时控制:ESPTIMER可以以微秒级的精度进行定时,可以满足对时间精度要求较高的应用场景。
多种工作模式:ESPTIMER支持3种工作模式,包括单次定时器、重复定时器和高精度定时器。开发者可以灵活选择适合自己需求的工作模式。
多任务支持:ESPTIMER可以同时管理多个定时器任务,每个定时器任务可以独立运行,互不干扰。
灵活的任务调度:ESPTIMER提供了丰富的任务调度选项,例如在指定时间触发、循环执行、延时执行等。
ESPTIMER在很多应用中都发挥着重要作用,例如:
定时采集数据:开发者可以利用ESPTIMER实现定时采集传感器数据或其他外部设备的数据,以保持数据的及时性和准确性。
周期性任务:ESPTIMER可以周期性地执行某些任务,例如周期性发送数据、刷新显示、控制设备状态等。
定时触发操作:通过ESPTIMER,可以实现在指定时间点触发某些操作,例如定时启动、定时关闭或定时执行某些任务。
综上所述,ESPTIMER作为ESP32 IDF开发框架的一部分,为开发者提供了强大的定时器功能,可广泛应用于各种定时任务和周期性操作的场景。开发者可以根据自己的需求,灵活地利用ESPTIMER实现定时功能,提升系统的稳定性和效率。