bouton_isr.c
En ESP-IDF un botón se vigila por interrupción: la ISR se ejecuta en el flanco, la tarea imprime. El atributo IRAM_ATTR es obligatorio porque la flash puede no estar disponible durante la interrupción.
Hardware necesario
Una placa ESP32-H2 (RISC-V a 96 MHz, radio IEEE 802.15.4 solo — sin Wi-Fi) tipo DevKitM-1, alimentada por USB. 1 botón pulsador a GND (GPIO9 también es BOOT: pulsaciones cortas vale).
Cableado
Botón entre GPIO9 y GND; la resistencia pull-up se activa en gpio_config. Vale cualquier pin con matriz GPIO.
Funcionamiento
gpio_config arma la interrupción por flanco de bajada; la ISR solo incrementa un contador volatile (regla de oro: ISR corta). La tarea compara e imprime a 20 Hz, filtrando el rebote. Prográmelo con ESP-IDF (idf.py set-target esp32h2); el puerto USB-Serial/JTAG (GPIO26/27) sirve de consola y puerto de flash. Mantenga Boot + Reset para modo download si hace falta.
Para ir más lejos
Despierte el SoC con la misma interrupción (esp_sleep_enable_ext0_wakeup) para un detector a batería.
bouton_isr.c
// bouton_isr.c — interruption sur front, compte les appuis.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#define BROCHE 9 // bouton vers GND (GPIO9 = BOOT du DevKit)
static volatile int appuis = 0;
static const char *TAG = "bouton";
static void IRAM_ATTR sur_appui(void *arg)
{
appuis++; // le minimum en contexte d'ISR
}
void app_main(void)
{
gpio_config_t io = {
.pin_bit_mask = 1ULL << BROCHE,
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.intr_type = GPIO_INTR_NEGEDGE, // front descendant = appui
};
gpio_config(&io);
gpio_install_isr_service(0);
gpio_isr_handler_add(BROCHE, sur_appui, NULL);
int vu = 0;
while (1) {
if (vu != appuis) { vu = appuis; ESP_LOGI(TAG, "appui n°%d", vu); }
vTaskDelay(pdMS_TO_TICKS(50)); // anti-rebond par echantillonnage
}
}