Table of Contents
Example: Using a Timer to Trigger an Interrupt
#include "driver/timer.h"
#define TIMER_DIVIDER 16 // Timer divider
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // Timer scale
#define TIMER_INTERVAL_SEC 1 // Interval in seconds
void IRAM_ATTR onTimer(){
Serial.println("Timer interrupt triggered!");
// Add your timer interrupt handling code here
}
void setup() {
Serial.begin(115200);
// Configure timer 0
timer_config_t config;
config.divider = TIMER_DIVIDER;
config.counter_dir = TIMER_COUNT_UP;
config.counter_en = TIMER_START;
config.autoreload = true;
config.alarm_en = TIMER_ALARM_EN;
config.intr_type = TIMER_INTR_LEVEL;
timer_init(TIMER_GROUP_0, TIMER_0, &config);
// Set timer alarm to trigger after the specified interval
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_INTERVAL_SEC * TIMER_SCALE);
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
// Attach the interrupt to the timer
timer_isr_register(TIMER_GROUP_0, TIMER_0, onTimer, NULL, ESP_INTR_FLAG_IRAM, NULL);
// Start the timer
timer_start(TIMER_GROUP_0, TIMER_0);
}
void loop() {
// Main loop does nothing; the timer ISR takes care of the interrupt
}
Explanation:
- Timer Setup: The timer is configured with a divider, an interval, and an alarm.
- Interrupt Service Routine (ISR): The ISR onTimer() is triggered each time the timer alarm occurs (every 1 second in this example).
- ISR Handling: The ISR handles the interrupt and prints a message every time the timer interrupt is triggered.
Key Points to Consider:
- Short ISR Functions: ISRs should be kept short and efficient because the main program is paused while the ISR runs. Avoid delays, Serial.print(), or long computations in the ISR.
- Global Variables in ISR: Be cautious when modifying global variables inside an ISR. Use volatile for variables that are shared between the ISR and the main code to ensure proper synchronization.
- Interrupt Priority: ESP32 has configurable interrupt priorities, allowing more important interrupts to preempt others.