盡管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