ESP32 has 4 individual hardware timers, arranged as 2 timers x 2 timer groups.
All 4 are 64-bit generic timers based on 16-bit prescalers and 64-bit auto-reload-capable up / down counters.
Resources
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/timer.html
CMakeLists.txt REQUIRES
Ensure the following is added to the REQUIRES section of your CMakeLists.txt file in the \main folder:
REQUIRES
esp_timer
Example using Timer TG0 as 100uS irq Timer
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "rom/ets_sys.h"
#include "rom/gpio.h"
#include <stddef.h>
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#include "driver/timer.h"
static intr_handle_t s_timer_handle;
//*****************************************
//*****************************************
//********** TIMER TG0 INTERRUPT **********
//*****************************************
//*****************************************
static void timer_tg0_isr(void* arg)
{
static int io_state = 0;
//Reset irq and set for next time
TIMERG0.int_clr_timers.t0 = 1;
TIMERG0.hw_timer[0].config.alarm_en = 1;
//----- HERE EVERY #uS -----
//Toggle a pin so we can verify the timer is working using an oscilloscope
io_state ^= 1; //Toggle the pins state
gpio_set_direction(GPIO_NUM_5, GPIO_MODE_OUTPUT);
gpio_set_level(GPIO_NUM_5, io_state);
}
//******************************************
//******************************************
//********** TIMER TG0 INITIALISE **********
//******************************************
//******************************************
void timer_tg0_initialise (int timer_period_us)
{
timer_config_t config = {
.alarm_en = true, //Alarm Enable
.counter_en = false, //If the counter is enabled it will start incrementing / decrementing immediately after calling timer_init()
.intr_type = TIMER_INTR_LEVEL, //Is interrupt is triggered on timer’s alarm (timer_intr_mode_t)
.counter_dir = TIMER_COUNT_UP, //Does counter increment or decrement (timer_count_dir_t)
.auto_reload = true, //If counter should auto_reload a specific initial value on the timer’s alarm, or continue incrementing or decrementing.
.divider = 80 //Divisor of the incoming 80 MHz (12.5nS). Default the clock source is APB_CLK (typically 80 MHz). (Range 2 to 65536). 80 = 1uS per timer tick
};
timer_init(TIMER_GROUP_0, TIMER_0, &config);
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0);
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, timer_period_us); //(group_num, timer_num, alarm_value) alarm_value (uint64) is how many timer ticks before the irq will be fired. (divider x alarm_value)=Time period, so 1uS x 100 = 100uS
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
timer_isr_register(TIMER_GROUP_0, TIMER_0, &timer_tg0_isr, NULL, 0, &s_timer_handle);
timer_start(TIMER_GROUP_0, TIMER_0);
}
/* In your initialise function somewhere
//----- CREATE OUR HARDWARE TIMER -----
timer_tg0_initialise(100);
*/

4 years ago
Thanks
5 years ago
Excellent summary. just what I needed to know as I bridge from atmega to esp32.
5 years ago
Thanks a lot!