ESP定时器(1)
ESP定时器(1)
一、概述
使用ESP定时器可以创建软件定时器并在超时时调用其回调函数(分发回调函数)。尤其适用于当软件需要执行延迟操作或周期性操作的场景,例如:延迟启动设备或停止设备、周期性采样传感器数据等。
ESP定时器可以简化一些操作,例如:管理多个定时器、分发回调函数、处理时钟频率变化(如果启用了动态调频),以及从浅睡眠中唤醒后保持准确的时间。
如果应用场景对实时性能要求较高(例如需要生成波形),或要求定时器分辨率可配置,建议使用GPTimer。此外,GPTimer还提供一些其它功能,例如事件捕获。
FreeRTOS有其单独的软件定时器,但分辨率比ESP定时器低得多,优势在于 FreeRTOS 定时器有更好的移植性,因为它不依赖于 ESP-IDF。
二、功能与概念
ESP定时器API提供:
-
一次性和周期性定时器
-
多种分发回调函数的方法
-
处理过期回调函数
-
计数器位宽:52位
-
时间分辨率:1 us
1. 一次性和周期性定时器
- 一次性定时器
一次性定时器到期时仅调用一次回调函数便停止运行。一次性定时器适用于单次延迟操作,例如在指定时间间隔后关闭设备或读取传感器。
- 周期性定时器
周期性定时器在到期时会调用回调函数并自动重启,回调函数会在指定时间间隔内被反复调用,直至手动暂停周期性定时器。周期性定时器适用于重复操作,例如采样传感器数据、更新显示信息或生成波形。
2. 分发回调函数的方法
定时器回调函数可以使用以下方法进行分发:
- 任务分发法(默认)
从单个高优先级ESP定时器任务中分发定时器回调函数(esp_timer任务(由ISR通知)> 回调)。适用于对时序要求不高的定时器回调函数。
- 中断分发法 (ESP_TIMER_ISR)
直接从中断处理程序分发定时器回调函数(ISR > 回调)。适合运行时间仅为几微秒的简单、低延迟定时器回调函数。能确保事件和执行回调之间的延迟较短。不受其它活动任务影响。
(1)任务分发细节
在ESP定时器任务中,回调函数是串行执行的,若多个超时同时发生,执行前一项回调函数会延迟后续回调函数的执行。因此,建议尽量保持回调函数简短。如果需要回调函数执行更多工作,应使用FreeRTOS原语(如队列和信号量)将工作推迟到低优先级任务中执行。
如果有其它更高优先级的FreeRTOS任务正在运行(例如SPI flash操作),则回调函数的分发将被延迟,直到ESP定时器任务有机会再次运行。
为了确保任务的可预测性和及时执行,回调函数不应进行阻塞(等待资源)或让步(放弃控制)操作,否则将中断回调函数的串行执行。
(2)中断分发细节
使用中断分发法的定时器,其回调由中断处理程序执行。由于中断可以抢占所有任务,中断分发法带来的延迟较低。中断分发的定时器回调函数不应尝试阻塞,也不应尝试通过portYIELD_FROM_ISR()触发上下文切换,而应使用 esp_timer_isr_dispatch_need_yield() 函数。上下文切换将在处理完所有使用ISR分发法的定时器后进行。
使用中断分发的定时器时,应避免使用标准的日志记录或调试方法(例如printf)。若想调试应用程序或在控制台中显示某些信息,应使用ESP-IDF日志宏,例如ESP_DRAM_LOGI和 ESP_EARLY_LOGI等。这些宏专为在各种上下文(包括中断服务程序)中工作而设计。
3. 获取当前时间
可以使用便捷函数 esp_timer_get_time() 获取自ESP定时器初始化以来经过的时间。在调用app_main函数之前不久,ESP定时器会开始初始化。该便捷函数速度极快,没有能引入延迟或冲突的锁机制,因此可用于细粒度定时,在任务和ISR例程中的精度为1 μs。
与gettimeofday函数不同,esp_timer_get_time() 具有以下特点:
-
从深睡眠状态中唤醒后,初始化定时器将从零开始。
-
返回值没有时区设置或夏令时调整。
更多内容请看下回。
更多推荐



所有评论(0)