ESP32定時器使用

esp32定時器一共有2組,每組有兩個,每個定時器都是64位的。每一組還會包含一個看門狗定時器。結構如下:

定時器

定時器組0

定時器0

定時器1

WDT定時器

定時器組1

定時器0

定時器1

WDT定時器

定時器時鐘:

每個定時器都以 APB 時鐘(縮寫 APB_CLK,頻率通常為 80 MHz)作為基礎時鐘 。知道了時鐘頻率就好配置分頻值和計數值來產生自己想要的定時中斷。

例如我需要1s中產生一次定時器中斷;我可以把分頻值設為80,這個計數器的頻率為80mhz/80=1mhz,也就是1us計數器會記一個值。然後我再設定計數到1000000產生alarm中斷。1us*1000000=1s

下面用程式碼解釋下具體如何配置產生1s的定時器中斷:

定時器初始化

使用的是定時器組0的定時器0,簡稱為timer00

void timer00_init(){ timer_config_t config; config。divider = 80; //分頻值,預設時鐘是80mhz config。counter_dir = TIMER_COUNT_UP; config。counter_en = TIMER_PAUSE; config。alarm_en = TIMER_ALARM_EN; config。intr_type = TIMER_INTR_LEVEL; config。auto_reload = 1; //使能自動裝載 timer_init(TIMER_GROUP_0, TIMER_0, &config); timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL); timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 1000000); timer_enable_intr(TIMER_GROUP_0, TIMER_0); timer_isr_register(TIMER_GROUP_0, TIMER_0, timer00_isr, (void *) TIMER_0, ESP_INTR_FLAG_IRAM, NULL); timer_start(TIMER_GROUP_0, TIMER_0);}

如上程式碼,從函式名稱基本上也可以看出來每一步的作用。

根據結構體進行timer的初始化

設定定時器計數器值,這個值需要注意,下次自動裝載的時候用的也是這個值

設定alarm報警計數值

使能timer中斷

中斷服務函式註冊,這個函式請看下面

啟動定時器

定時器中斷服務函式

void IRAM_ATTR timer00_isr(void *para){ int timer_idx = (int) para; //獲取定時器中斷狀態 uint32_t intr_status = TIMERG0。int_st_timers。val; if ((intr_status & BIT(timer_idx)) && timer_idx == TIMER_0) { TIMERG0。int_clr_timers。t0 = 1; //清除中斷標誌 } TIMERG0。hw_timer[timer_idx]。config。alarm_en = TIMER_ALARM_EN; //再次使能alarm uart_write_bytes(UART_NUM_0, (char *)“=======\r\n”, 9); //透過串列埠0打印出來,中斷服務函式中不能使用printf}

可以看到該中斷服務有個引數para,該引數對應timer_isr_register()第四個引數,當然也可以不使用。如果使用了引數,該中斷服務函式還有個限制,就必須放在RAM中執行,及在中斷服務函式名稱前加上IRAM_ATTR 。

中斷函式處理流程就很簡單。

先獲取定時器中斷狀態

清除中斷標誌

再次使能定時器alarm,這個地方比較關鍵。假如不再次使能定時器alarm只會觸發這一次。要持續1s觸發就要再次開啟

ESP32定時器使用