一、 簡介
- 獲取時(shí)間戳
- 周期性任務(wù)
本文主要內(nèi)容參考 官網(wǎng)API文檔
本文主要代碼參考 來自這里
ESP32-C3 有2個(gè)定時(shí)器組,每個(gè)組有2個(gè)定時(shí)器,共有4個(gè)定時(shí)器。
每組定時(shí)器包括一個(gè)普通定時(shí)器和一個(gè)看門狗定時(shí)器。
在 timer_types.h 里可以看到結(jié)構(gòu)體的定義:
typedef enum {
TIMER_GROUP_0 = 0, /*!
每個(gè)通用硬件定時(shí)器都是基于16位預(yù)分頻器和64位自動(dòng)重載功能的向上/向下計(jì)數(shù)的64位通用定時(shí)器。
二、使用步驟
- 資源分配
- 設(shè)置和獲取計(jì)數(shù)器值
- 設(shè)置報(bào)警動(dòng)作
- 注冊事件回調(diào)函數(shù)
- 使能或禁用定時(shí)器
- 啟動(dòng)和停止定時(shí)器
其它的操作有:
三、操作函數(shù)
1. 基本操作
(1)定時(shí)器實(shí)例gptimer_handle_t
(2) 定時(shí)器配置結(jié)構(gòu)體gptimer_config_t
使用結(jié)構(gòu)體 gptimer_config_t 來創(chuàng)建定時(shí)器實(shí)例, gptimer_config_t 結(jié)構(gòu)體的屬性值:
- gptimer_config_t::clk_src 選擇定時(shí)器的時(shí)鐘源,枚舉值: gptimer_clock_source_t
- gptimer_config_t::direction 設(shè)置定時(shí)器的計(jì)數(shù)方向,枚舉值: gptimer_count_direction_t
- gptimer_config_t::resolution_hz 設(shè)置內(nèi)部計(jì)數(shù)器的分辨率,計(jì)數(shù)器滴答一次用時(shí)秒數(shù)為:1 r e s o l u t i o n _ h z \\frac {1} {resolution_hz} resolution _hz1
- gptimer_config_t::intr_shared 設(shè)置是否將定時(shí)器中斷源標(biāo)記為共享源。
示例:
// 配置定時(shí)器,默認(rèn)時(shí)鐘源:APB
timer_config_t config = {
.divider = TIMER_DIVIDER, //定時(shí)器預(yù)分頻;esp32-c3的APB_CLK=80MHz,80MHz/TIMER_DIVIDER(16)=5MHz
.counter_dir = TIMER_COUNT_UP, //計(jì)數(shù)器向上計(jì)數(shù),從0開始
.counter_en = TIMER_PAUSE, //計(jì)數(shù)器暫時(shí)中止
.alarm_en = TIMER_ALARM_EN, //定時(shí)器警報(bào)使能
.auto_reload = auto_reload, //1:定時(shí)器硬件在警報(bào)事件后自動(dòng)重裝載;0:則相反
};
(3) 定時(shí)器初始化timer_init()
示例:
/*
* 函數(shù)功能:初始化和配置定時(shí)器
* group_num:定時(shí)器分組值, 從0開始
* timer_num:定時(shí)器序號,從0開始 【一組定時(shí)器包含:普通定時(shí)器,看門狗定時(shí)器】
* *config: 定時(shí)器配置結(jié)構(gòu)體
*/
timer_init(group, timer, &config);
(3) 設(shè)置定時(shí)器初值timer_set_counter_value()
示例:
// 設(shè)置定時(shí)器值,如果設(shè)置了auto_reload,則報(bào)警后會(huì)也會(huì)重置為此值
timer_set_counter_value(group, timer, 0);
(4)設(shè)置報(bào)警值timer_set_alarm_value()
示例:
// 設(shè)置報(bào)警值、使能中斷ISR
timer_set_alarm_value(group, timer, timer_interval_sec * TIMER_SCALE);
(5)使用定時(shí)器timer_enable_intr()
示例:
// 使能定時(shí)器組(group)、定時(shí)器x(timer)中斷
timer_enable_intr(group, timer);
(6) 定時(shí)器添加ISR中斷回調(diào)timer_isr_callback_add()
示例:
// 定時(shí)器添加ISR中斷回調(diào)函數(shù)
timer_info_t *timer_info = calloc(1, sizeof(timer_info_t));
timer_info->timer_group = group;
timer_info->timer_idx = timer;
timer_info->auto_reload = auto_reload;
timer_info->alarm_interval = timer_interval_sec;
timer_isr_callback_add(group, timer, timer_group_isr_callback, timer_info, 0);//???
(7)啟動(dòng)定時(shí)器timer_start()
示例:
timer_start(group, timer);
(8) 獲取定時(shí)器值timer_get_counter_value()
示例:
uint64_t task_counter_value;
// 獲取定時(shí)器組,中定時(shí)器,的計(jì)數(shù)器的值;
timer_get_counter_value(evt.info.timer_group, evt.info.timer_idx, &task_counter_value);
2. 其它操作
(1) 創(chuàng)建新定時(shí)器gptimer_new_timer()
示例: 創(chuàng)建分辨率為1 MHz 的通用定時(shí)器:
gptimer_handle_t gptimer = NULL;
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us
};
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
(2) 設(shè)置和獲取計(jì)數(shù)值gptimer_get_raw_count()
gptimer_get_raw_count 用來獲取計(jì)數(shù)值。
- 創(chuàng)建計(jì)數(shù)器后,內(nèi)部計(jì)數(shù)器將默認(rèn)重置為0
- 計(jì)數(shù)值重置時(shí),將會(huì)從新值計(jì)數(shù)。
- 計(jì)數(shù)值達(dá)最大值后將重置,最大值與SOC宏: SOC_TIMER_GROUP_COUNTER_BIT_WIDTH 有關(guān)。
3. 使能和禁用定時(shí)器
(1)使能gptimer_enable()
此函數(shù)功能:
- 將定時(shí)器驅(qū)動(dòng)的狀態(tài)從init切換為enable
- 如果gptimer_register_event_callbacks() 已經(jīng)延遲安裝中斷服務(wù),此函數(shù)將使能中斷服務(wù)
- 如果選擇了特定的時(shí)鐘源,此函數(shù)將獲取適當(dāng)?shù)?a target="_blank">電源管理鎖。
(2)禁用gptimer_disable
4. 啟動(dòng)和停止定時(shí)器
(1)啟動(dòng)gptimer_start()
(2)停止gptimer_stop()
四、示例程序
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "driver/timer.h"
#define TIMER_DIVIDER (16) // Hardware timer clock divider
// 計(jì)數(shù)值轉(zhuǎn)為秒
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER)
typedef struct {
// 定時(shí)器組號
int timer_group;
// 定時(shí)器序號
int timer_idx;
// 報(bào)警時(shí)間
int alarm_interval;
// 是否自動(dòng)重裝
bool auto_reload;
} timer_info_t;
// 定義一個(gè)示例結(jié)構(gòu)體
typedef struct {
// 定時(shí)器的參數(shù)
timer_info_t info;
// 計(jì)數(shù)器值
uint64_t timer_counter_value;
} timer_event_t;
// 主程序接收報(bào)警數(shù)據(jù)的隊(duì)列
static xQueueHandle s_timer_queue;
/*
* A simple helper function to print the raw timer counter value
* and the counter value converted to seconds
*/
static void inline print_timer_counter(uint64_t counter_value)
{
printf("Counter: 0x%08x%08x \\t", (uint32_t) (counter_value >> 32),
(uint32_t) (counter_value));
printf("Time : %.8f s\\r\\n", (double) counter_value / TIMER_SCALE);
}
/**
* 報(bào)警回調(diào)函數(shù)
* @param args timer_info_t結(jié)構(gòu)體
* @return
*/
static bool IRAM_ATTR timer_group_isr_callback(void *args)
{
// 計(jì)算回調(diào)函數(shù)返回值
BaseType_t high_task_awoken = pdFALSE;
timer_info_t *info = (timer_info_t *) args;
// 在ISR中獲取計(jì)數(shù)器值
uint64_t timer_counter_value =
timer_group_get_counter_value_in_isr(info->timer_group, info->timer_idx);
// 將定時(shí)器中斷響應(yīng)的定時(shí)器賦予結(jié)構(gòu)體變量evt
timer_event_t evt = {
.info.timer_group = info->timer_group,
.info.timer_idx = info->timer_idx,
.info.auto_reload = info->auto_reload,
.info.alarm_interval = info->alarm_interval,
.timer_counter_value = timer_counter_value
};
// 定時(shí)器組中的定時(shí)器,是否有自動(dòng)重載
if (!info->auto_reload) {
timer_counter_value += info->alarm_interval * TIMER_SCALE;
// 重置定時(shí)器組中定時(shí)器的時(shí)間間隔(定時(shí)器自身的時(shí)間間隔)
timer_group_set_alarm_value_in_isr(info->timer_group, info->timer_idx, timer_counter_value);
}
// 以隊(duì)列形式把數(shù)據(jù)發(fā)送到主函數(shù),消息存儲在結(jié)構(gòu)體evt中
// high_task_awoken 用于接收返回值
xQueueSendFromISR(s_timer_queue, &evt, &high_task_awoken);
return high_task_awoken == pdTRUE;
}
/**
* @brief 初始化定時(shí)器
*
* @param group 定時(shí)器組序號,從0開始
* @param timer timer ID, 從0開始
* @param auto_reload 是否自動(dòng)重載
* @param timer_interval_sec 間隔
*/
static void timer_config_start(int group, int timer, bool auto_reload, int timer_interval_sec)
{
// 配置定時(shí)器,默認(rèn)時(shí)鐘源:APB
timer_config_t config = {
.divider = TIMER_DIVIDER, //定時(shí)器預(yù)分頻;esp32-c3的APB_CLK=80MHz,80MHz/TIMER_DIVIDER(16)=5MHz
.counter_dir = TIMER_COUNT_UP, //計(jì)數(shù)器向上計(jì)數(shù),從0開始
.counter_en = TIMER_PAUSE, //計(jì)數(shù)器暫時(shí)中止
.alarm_en = TIMER_ALARM_EN, //定時(shí)器警報(bào)使能
.auto_reload = auto_reload, //1:定時(shí)器硬件在警報(bào)事件后自動(dòng)重裝載;0:則相反
};
/*
* 函數(shù)功能:初始化和配置定時(shí)器
* group_num:定時(shí)器分組值, 從0開始
* timer_num:定時(shí)器序號,從0開始 【一組定時(shí)器包含:普通定時(shí)器,看門狗定時(shí)器】
* *config: 定時(shí)器配置結(jié)構(gòu)體
*/
timer_init(group, timer, &config);
// 設(shè)置定時(shí)器值,如果設(shè)置了auto_reload,則報(bào)警后會(huì)也會(huì)重置為此值
timer_set_counter_value(group, timer, 0);
// 設(shè)置報(bào)警值、使能中斷ISR
timer_set_alarm_value(group, timer, timer_interval_sec * TIMER_SCALE);
// 使能定時(shí)器組(group)、定時(shí)器x(timer)中斷
timer_enable_intr(group, timer);
// 定時(shí)器添加ISR中斷回調(diào)函數(shù)
timer_info_t *timer_info = calloc(1, sizeof(timer_info_t));
timer_info->timer_group = group;
timer_info->timer_idx = timer;
timer_info->auto_reload = auto_reload;
timer_info->alarm_interval = timer_interval_sec;
timer_isr_callback_add(group, timer, timer_group_isr_callback, timer_info, 0);//???
// 啟動(dòng)定時(shí)器
timer_start(group, timer);
}
void app_main(void)
{
// xQueueCreate是freeRTOS宏,用于創(chuàng)建隊(duì)列實(shí)例
s_timer_queue = xQueueCreate(10, sizeof(timer_event_t));
// 配置定時(shí)器組1,中的定時(shí)器0,無自動(dòng)重裝,間隔是5s
timer_config_start(TIMER_GROUP_1, TIMER_0, false, 10);
while (1) {
timer_event_t evt;
// 等待隊(duì)列事件,時(shí)間是永遠(yuǎn)等待
xQueueReceive(s_timer_queue, &evt, portMAX_DELAY);
// 定時(shí)器組自動(dòng)重裝
if (evt.info.auto_reload) {
printf("====== Timer Group with auto reload ======\\n");
} else {
printf("====== Timer Group without auto reload ======\\n");
}
printf("------ Group[%d], timer[%d] alarm event ------\\n", evt.info.timer_group, evt.info.timer_idx);
// 打印事件上報(bào)的計(jì)數(shù)器值
printf("[ evt.timer_counter_value ] ");
print_timer_counter(evt.timer_counter_value);
// 直接從定時(shí)器獲取計(jì)數(shù)器值
printf("[timer.timer_counter_value] ");
uint64_t task_counter_value;
// 獲取定時(shí)器組,中定時(shí)器,的計(jì)數(shù)器的值;
timer_get_counter_value(evt.info.timer_group, evt.info.timer_idx, &task_counter_value);
print_timer_counter(task_counter_value);
}
}
運(yùn)行結(jié)果:
====== Timer Group without auto reload ======
------ Group[1], timer[0] alarm event ------
[ evt.timer_counter_value ] Counter: 0x0000000002faf089 Time : 10.00000180 s
[timer.timer_counter_value] Counter: 0x0000000002fb43ab Time : 10.00425820 s
====== Timer Group without auto reload ======
------ Group[1], timer[0] alarm event ------
[ evt.timer_counter_value ] Counter: 0x0000000005f5e112 Time : 20.00000360 s
[timer.timer_counter_value] Counter: 0x0000000005f632f5 Time : 20.00419620 s
如果 timer_config_start函數(shù)的auto_reload設(shè)置為true,則輸出示例:
可以看到達(dá)到報(bào)警值后,計(jì)數(shù)器值會(huì)還原。
-
硬件
+關(guān)注
關(guān)注
11文章
3460瀏覽量
67193 -
分頻器
+關(guān)注
關(guān)注
43文章
490瀏覽量
50826 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3287瀏覽量
117205 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4370瀏覽量
64193 -
ESP32-C3
+關(guān)注
關(guān)注
0文章
9瀏覽量
626
發(fā)布評論請先 登錄
淺談ESP32-C3與ESP32-S3芯片
ESP32-C3芯片的性價(jià)比有多高

ESP32-C3芯片特性介紹
ESP32-C3芯片到底有哪些特性
ESP32-C3模組芯片的功能特性
基于nanoESP32-C3開發(fā)板用ESP32-c3下試跑Zephyr
ESP32 之 ESP-IDF 教學(xué)(三)——通用硬件定時(shí)器(Timer)

【DFRobot Beetle ESP32-C3開發(fā)板試用體驗(yàn)】車載導(dǎo)航天氣掛件?

【DFRobot Beetle ESP32-C3開發(fā)板試用體驗(yàn)】與GNSS模塊串口通信

【DFRobot Beetle ESP32-C3開發(fā)板試用體驗(yàn)】開箱和1602A顯示

DFRobot Beetle ESP32-C3 DIY運(yùn)動(dòng)按鈕 讓你隨時(shí)隨地動(dòng)起來

ESP32-C3開發(fā)板設(shè)計(jì)指南

評論