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);
*/

Comments

  1. E.Martins

    4 years ago

    Thanks

  2. Paul B.

    5 years ago

    Excellent summary. just what I needed to know as I bridge from atmega to esp32.

  3. UT2UH

    5 years ago

    Thanks a lot!