ESP32高分辨率计时器笔记

尽管FreeRTOS提供了软件计时器,但这些计时器有一些限制:

  • 最大分辨率等于RTOS滴答周期

  • 计时器回调从低优先级任务分派

硬件计时器不受这两个限制,但是通常它们使用起来不太方便。例如,应用组件可能需要定时器事件在将来的特定时间触发,但是硬件定时器仅包含一个用于中断产生的“比较”值。这意味着需要在硬件计时器之上构建一些功能来管理挂起事件列表,以便在发生相应的硬件中断时可以调度这些事件的回调。

esp_timer 一组API提供了一次性的计时器和定期的计时器,微秒级的时间分辨率以及64位范围。

 

基于ESP-IDF4.1

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <unistd.h>
 4 #include "esp_timer.h"
 5 #include "esp_log.h"
 6 #include "esp_sleep.h"
 7 #include "sdkconfig.h"
 8 
 9 static void periodic_timer_callback(void* arg);
10 static void oneshot_timer_callback(void* arg);
11 
12 static const char* TAG = "example";
13 
14 void app_main(void)
15 {
16     /* 
17      * 创建两个计时器:
18      * 1.每0.5秒运行的一个周期性计时器,并且打印消息
19      * 2.五秒后执行的一次性计时器,并且每1秒重启计时器
20      */
21 
22     //创建周期性计时器
23     const esp_timer_create_args_t periodic_timer_args = {
24             .callback = &periodic_timer_callback,
25             //自定义名称
26             .name = "periodic"
27     };
28 
29     esp_timer_handle_t periodic_timer;
30     ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
31 
32     //创建一次性计时器
33     const esp_timer_create_args_t oneshot_timer_args = {
34             .callback = &oneshot_timer_callback,
35             //指定的参数将会传给计时器回调函数
36             .arg = (void*) periodic_timer,
37             .name = "one-shot"
38     };
39     esp_timer_handle_t oneshot_timer;
40     ESP_ERROR_CHECK(esp_timer_create(&oneshot_timer_args, &oneshot_timer));
41 
42     //启动计时器
43     ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 500000));
44     ESP_ERROR_CHECK(esp_timer_start_once(oneshot_timer, 5000000));
45     ESP_LOGI(TAG, "Started timers, time since boot: %lld us", esp_timer_get_time());
46 
47     // 每2秒打印计时器调试信息到控制台
48     for (int i = 0; i < 5; ++i) {
49         ESP_ERROR_CHECK(esp_timer_dump(stdout));
50         usleep(2000000);
51     }
52 
53 
54     //轻度睡眠中,时间继续保持。轻度睡眠后计时器正确执行
55     ESP_LOGI(TAG, "Entering light sleep for 0.5s, time since boot: %lld us",esp_timer_get_time());
56     ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(500000));
57     esp_light_sleep_start();
58     ESP_LOGI(TAG, "Woke up from light sleep, time since boot: %lld us", esp_timer_get_time());
59 
60     //让计时器再运行一会
61     usleep(2000000);
62 
63     //停止和清除计时器
64     ESP_ERROR_CHECK(esp_timer_stop(periodic_timer));
65     ESP_ERROR_CHECK(esp_timer_delete(periodic_timer));
66     ESP_ERROR_CHECK(esp_timer_delete(oneshot_timer));
67     ESP_LOGI(TAG, "Stopped and deleted timers");
68 }
69 
70 //周期性计时器回调函数
71 static void periodic_timer_callback(void* arg)
72 {
73     int64_t time_since_boot = esp_timer_get_time();
74     ESP_LOGI(TAG, "Periodic timer called, time since boot: %lld us", time_since_boot);
75 }
76 
77 //一次性计时器回调函数
78 static void oneshot_timer_callback(void* arg)
79 {
80     int64_t time_since_boot = esp_timer_get_time();
81     ESP_LOGI(TAG, "One-shot timer called, time since boot: %lld us", time_since_boot);
82     esp_timer_handle_t periodic_timer_handle = (esp_timer_handle_t) arg;
83     //启动运行的计时器,首先需要先停止它
84     ESP_ERROR_CHECK(esp_timer_stop(periodic_timer_handle));
85     ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer_handle, 1000000));
86     time_since_boot = esp_timer_get_time();
87     ESP_LOGI(TAG, "Restarted periodic timer with 1s period, time since boot: %lld us",time_since_boot);
88 }

 

原文:https://gitee.com/EspressifSystems/esp-idf/tree/master/examples/system/esp_timer

posted @ 2020-11-12 10:58  kerwin cui  阅读(1797)  评论(0编辑  收藏  举报