typedef struct
{ timer_alarm_t alarm_en; /*!< Timer alarm enable */ timer_start_t counter_en; /*!< Counter enable */ timer_intr_mode_t intr_type; /*!< Interrupt mode */ timer_count_dir_t counter_dir; /*!< Counter direction */ timer_autoreload_t auto_reload; /*!< Timer auto-reload */ uint32_t divider; /*!< Counter clock divider. The divider's range is from from 2 to 65536. */ } timer_config_t;
定時器初始化結構體成員6個,從上到下依次是,中斷使能,計數使能,中斷模式,計數方向,自動重載,分頻系數。
timer_init(TIMER_GROUP_0,TIMER_1,&timerconfig);
初始化結構體后,調用初始化函數,三個參數包括,定時器組號,定時器編號,初始化結構體地址
timer_set_counter_value(TIMER_GROUP_0,TIMER_1,0x00000000ULL); timer_set_alarm_value(TIMER_GROUP_0,TIMER_1,TIMER_BASE_CLK/8); timer_enable_intr(TIMER_GROUP_0,TIMER_1); timer_isr_register(TIMER_GROUP_0,TIMER_1,timer_isr_handler,(void *)TIMER_1,ESP_INTR_FLAG_IRAM,NULL); timer_start(TIMER_GROUP_0,TIMER_1);
接下來需要調用設定定時器初值的函數,設定警報值的函數,使能定時器中斷,並注冊定時器中斷服務函數,注冊定時器中斷服務函數的參數有
定時器中斷服務函數的指針以及傳參和中斷函數存儲地址分類。
接下來就需要編寫定時器中斷服務函數
void IRAM_ATTR timer_isr_handler(void *arg) { u32_t intr=timer_group_get_intr_status_in_isr(TIMER_GROUP_0); // if(intr&TIMER_INTR_T0) // { // timer_group_clr_intr_status_in_isr(TIMER_GROUP_0,TIMER_1); // gpio_set_level(LED_PIN,1-gpio_get_level(LED_PIN)); // timer_group_enable_alarm_in_isr(TIMER_GROUP_0,TIMER_1); // }
if(TIMER_1==(u32_t)arg) { timer_group_clr_intr_status_in_isr(TIMER_GROUP_0,TIMER_1); gpio_set_level(LED_PIN,1-gpio_get_level(LED_PIN)); timer_group_enable_alarm_in_isr(TIMER_GROUP_0,TIMER_1); } }
在中斷服務函數中需要判斷下產生中斷的定時器是否是我們設定的定時器,這是為了在使用多個定時器時可以把同一組的定時器中斷服務
都注冊在一個函數,區分產生中斷的外設可以根據檢測定時器分組中的中斷狀態標志位,看對應的T0位是否為1,也可以根據我們注冊中斷服務函數時
傳入的參數來判斷中斷的定時器。
需要注意的是,定時器中斷標志位需要軟件手動清除,如果想繼續使用鬧鈴功能,需要重新使能鬧鈴功能。
上面是ESP32的硬件定時器,在軟件中還有一種esp_timer即軟件定時器
/** * @brief Timer configuration passed to esp_timer_create */ typedef struct { esp_timer_cb_t callback; //!< Function to call when timer expires
void* arg; //!< Argument to pass to the callback
esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR
const char* name; //!< Timer name, used in esp_timer_dump function
bool skip_unhandled_events; //!< Skip unhandled events for periodic timers
} esp_timer_create_args_t;
這是esp_timer創建時所需參數的結構體,結構體成員有5個成員
第一個是當定時器到達設定值時回調函數的地址。
第二個是回調函數的傳遞參數
第三個是調用回調函數的方式,是從task中回調還是從ISR中回調,esp32目前只支持task中回調。所以不用設置
第四個是定時器的名字
第五個是當周期定時發生時是否跳過未處理的事件
esp_err_t err=esp_timer_create(&esp_timer_args_t1,&esp_timer_handle_timer1); err=esp_timer_start_periodic(esp_timer_handle_timer1,1000000); if(err==ERR_OK) printf("esp-timer initialation is ok!\n");
初始化參數賦值完后就可以調用創建函數了,創建函數中的參數包括創建參數的結構體和esp_timer句柄,后期會用到句柄。
啟動定時器如果單次定時使用start_once,如果是周期性使用調用start_periodic
因為軟件定時器的周期是固定的1us所以設定的溢出值是以us位單位。剩下的就是在回調函數中編寫我們需要的功能了。
軟件定時器不需要清楚標志位,在定時器計數達到設定值后會調用回調函數並將計數值清0。