赞
踩
ESP Timer是ESP32-S3的一个强大功能,它允许创建软件定时器并在超时时调用它们的回调函数。这对于需要执行延迟或周期性操作的用户软件非常有用,例如延迟设备启动/停止或周期性采样传感器数据。
对于需要较好实时性能(如生成波形)或可配置定时器分辨率的应用场景,建议改用GPTimer。此外,GPTimer 还具有 ESP Timer 中没有的功能,例如事件捕获。
我们先来简单的了解一下系统定时器的结构图,对于后面的编程会有一个较好的思路
ESP32-S3 芯片内置一组 52 位系统定时器。该定时器可用于生成操作系统所需的滴答定时中断,也可用作普通定时器生成周期或单次延时中断。
系统定时器内置两个计数器(UNIT0 和 UNIT1)以及三个比较器(COMP 0、COMP1 和 COMP2)。比较器用于监控计数器的计数值是否达到报警值。定时器的功能块图见上图
ESP32-S3 内置了一个 52 位的高精度计数器,能够基于外部晶体振荡器 XTAL_CLK 运行,该振荡器工作频率通常为 40MHz。
计数器首先对 XTAL_CLK 进行了分频操作,其中在一个计数周期内产生了一个频率为原始 XTAL_CLK 频率三分之一(fXTAL_CLK/3)的时钟信号。
然后,在接下来的计数周期中,又产生了频率为 XTAL_CLK 一半(fXTAL_CLK/2)的时钟信号。
因此,计数器实际使用的平均时钟频率 CNT_CLK,需要把两个不同频率周期的时钟信号综合考虑。假设这两个阶段交替进行且每个阶段占同样比例的时间,则 CNT_CLK 的实际平均频率为:
C N T _ C L K = 1 2 × ( 1 3 + 1 2 ) × f X T A L _ C L K {CNT\_CLK} = \frac{1}{2} \times \left( \frac{1}{3} + \frac{1}{2} \right) \times f_{XTAL\_CLK} CNT_CLK=21×(31+21)×fXTAL_CLK
其中,
f
X
T
A
L
_
C
L
K
=
40
M
H
z
f_{XTAL\_CLK} = 40MHz
fXTAL_CLK=40MHz
代入计算得:
C
N
T
_
C
L
K
=
1
2
×
(
1
3
+
1
2
)
×
40
,
000
,
000
H
z
{CNT\_CLK} = \frac{1}{2} \times \left( \frac{1}{3} + \frac{1}{2} \right) \times 40,000,000Hz
CNT_CLK=21×(31+21)×40,000,000Hz
简化后:
C
N
T
_
C
L
K
=
5
12
×
40
,
000
,
000
H
z
{CNT\_CLK} = \frac{5}{12} \times 40,000,000Hz
CNT_CLK=125×40,000,000Hz
最终得出:
C
N
T
_
C
L
K
≈
16
,
666
,
666.67
H
z
{CNT\_CLK} ≈ 16,666,666.67Hz
CNT_CLK≈16,666,666.67Hz
即 16MHz见下图1。每个 CNT_CLK 时钟周期,计数递增 1/16µs,即 16 个周期递增 1µs。
COMP0、COMP1、COMP2 均为 ESP32-S3 系统定时器内置的 52 位比较器。比较器同样使
用 XTAL_CLK 作为时钟源(40MHz)。
上图展示了系统定时器生成报警的过程。在上述过程中用到一个计数器(Timer Countern)和一个比较器(Timer Comparatorx),比较器将根据比较结果,生成报警中断。
关于更多的硬件资料可以看一下官方文档
系统定时器 (SYSTIMER)
ESP Timer API提供了以下功能:
以下是使用ESP Timer的一般步骤:
esp_timer_handle_t
类型的变量 my_timer
,用于存储定时器句柄。esp_timer_create()
函数创建一个定时器。esp_timer_start_once()
或esp_timer_start_periodic()
函数启动定时器。esp_timer_stop()
函数停止定时器。esp_timer_delete()
函数删除定时器。以下是一个使用ESP Timer的示例代码:
#include "esp_timer.h" void timer_callback(void* arg) { // 在这里执行你的回调函数 } void app_main(void) { esp_timer_handle_t my_timer; //用于存储定时器句柄 // 定义一个定时器结构体 esp_timer_create_args_t timer_args = { .callback = &timer_callback, //设置回调函数 // 可以添加其他参数 }; esp_timer_create(&timer_args, &my_timer); //将创建的定时器句柄存储到 my_timer 中。 // 启动定时器 esp_timer_start_once(my_timer, 1000000); // 1秒后执行回调函数 第二个参数单位为us // 停止定时器 esp_timer_stop(my_timer); // 删除定时器 esp_timer_delete(my_timer); }
关于更多的API功能可以看一次官方的文档
ESP定时器(高分辨率定时器)
实验将配置 ESP 定时器每间隔 1000 毫秒产生一次中断,并在其中断服务函数中改变一次 LED 的状态,具体的步骤如下:
①:设置 ESP 定时器的回调函数
②:创建一个事件
③:每周期内触发一次
/** * @file ESPtimer.h * @author 宁子希 (1589326497@qq.com) * @brief 高分辨率定时器(ESP定时器)驱动代码 * @version 0.1 * @date 2024-04-16 * * @copyright Copyright (c) 2024 * */ #ifndef __ESPTIMER_H__ #define __ESPTIMER_H__ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #include "esp_timer.h" #include "LED.h" //初始化初始化高分辨率定时器 void ESPtimer_init(uint64_t tps); //定时器回调函数 void ESPtimer_callback(void* arg); #endif
/** * @file ESPtimer.cpp * @author 宁子希 (1589326497@qq.com) * @brief 高分辨率定时器(ESP定时器)驱动代码 * @version 0.1 * @date 2024-04-16 * * @copyright Copyright (c) 2024 * */ #include "ESPtimer.h" //初始化初始化高分辨率定时器 void ESPtimer_init(uint64_t tps){ esp_timer_handle_t timer_handle; //定时器句柄 esp_timer_create_args_t timer_args={ .callback=&ESPtimer_callback, //回调函数 .arg=NULL, //回调函数参数 }; esp_timer_create(&timer_args,&timer_handle); //创建定时器 esp_timer_start_periodic(timer_handle,tps); //启动定时器 tps单位为us } //定时器回调函数 void IRAM_ATTR ESPtimer_callback(void* arg){ LED_A_TOGGLE(); LED_B_TOGGLE(); }
/** * @file main.c * @author 宁子希 (1589326497@qq.com) * @brief 高分辨率定时器(ESP定时器)实验 * @version 0.1 * @date 2024-04-16 * * @copyright Copyright (c) 2024 * */ #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #include "nvs_flash.h" #include "LED.h" #include "ESPtimer.h" void app_main(void){ esp_err_t ret; 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()); ret = nvs_flash_init(); } led_init(); ESPtimer_init(1000000); }
在完成编译和烧录操作后,可以看到板子上的 LED 在闪烁,LED 在 ESP 定时器的中断回调函数中被改变状态,LED 每间隔 1000 毫秒改变一次状态。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。