🛠 Interruptions GPIO et alarmes matérielles avec le Pico SDK
Objetivos
Salir del « polling »: en una placa RP2040 genérica sin LED ni botón integrados, quieres reaccionar instantáneamente a un evento externo y despertarte a una hora fija sin bloquear la CPU. El RP2040 proporciona para esto un controlador de interrupciones IO_BANK0 (niveles y flancos en cada GPIO) y un timer de 64 bits con 12 alarmas de hardware (datasheet RP2040). En C (Pico SDK), vas a combinar ambos para un botón limpio: IRQ en el flanco descendente, antirrebote mediante alarma diferida, CPU dormida entre ambos.
Material
- 1 × placa RP2040 genérica + cable USB de datos
- 1 × botón entre GP2 y GND, 1 × LED (con resistencia de 330 Ω) en GP15
- Pico SDK (C): proyecto CMake estándar, objetivo enlazado con
pico_stdlib pico_time hardware_irq
Código completo
// irq_alarm.c — IRQ front descendant + alarme anti-rebond (Pico SDK)
#include "pico/stdlib.h"
#include "hardware/irq.h"
#include "pico/time.h"
#define BTN 2
#define LED 15
// Exécutée 50 ms après le front : contexte d'interruption, rester bref.
bool confirmer_appui(alarm_id_t id, void *user) {
(void)id; (void)user;
if (!gpio_get(BTN)) { // toujours enfoncé ? vrai appui
gpio_put(LED, !gpio_get(LED));
}
return false; // one-shot
}
// Handler IO_BANK0 : au plus court, on planifie juste l'alarme.
void on_gpio(uint gpio, uint32_t events) {
(void)gpio; (void)events;
add_alarm_in_ms(50, confirmer_appui, NULL, true);
}
int main(void) {
stdio_init_all;
gpio_init(BTN); gpio_set_dir(BTN, GPIO_IN); gpio_pull_up(BTN);
gpio_init(LED); gpio_set_dir(LED, GPIO_OUT);
// active l'IRQ du front ET enregistre le callback IO_BANK0 partagé
gpio_set_irq_enabled_with_callback(BTN, GPIO_IRQ_EDGE_FALL,
true, &on_gpio);
while (true) {
__wfi; // le CPU s'end ; l'IRQ GPIO (ou une alarme) le réveille
}
}
Verificación esperada
Cada pulsación firme cambia el estado del LED una sola vez: la IRQ captura el flanco, la alarma vuelve a verificar el estado 50 ms después e ignora los rebotes (el contacto vibra ~1 ms). Añade un printf en el handler (con stdio_init_all) para confirmar que el __wfi termina correctamente con el evento. En un microamperímetro, el sueño WFI hace caer el consumo — la hoja de datos anuncia SLEEP ≈ 1,3 mA a 25 °C, medidor de sueño mediante.
Errores frecuentes
sleep_msoprintflargo en el handler de IRQ: el handler debe ser mínimo — programa una alarma, establece una bandera, procesa en otro lugar.- Olvidar
gpio_pull_up: la entrada queda flotante y dispara IRQs en ráfaga (tormenta de interrupciones, la CPU no hace nada más). - Handler no llamado:
gpio_set_irq_enabled_with_callbackactiva también la IRQ IO_BANK0 en el NVIC — un simplegpio_set_irq_enabledsin callback no hace nada. - Alarma que no se repite: el callback debe devolver
truepara ser reprogramado,falsepara un disparo único (one-shot). - Dos núcleos, mismas alarmas: las 12 alarmas de hardware son compartidas y el SDK reserva algunas para
sleep_ms— para uso a largo plazo, crea unaalarm_pool. - Rebote en la liberación ignorado: si también quieres el flanco ascendente, añade
GPIO_IRQ_EDGE_RISEa la máscara — un handler único gestiona ambos medianteevents.
Otros tutoriales para esta placa
- Piloter la LED RGB embarquée WS2812 d'une carte RP2040 générique
- Avoir une console série sur une carte sans pont USB (UART0)
- Jouer une mélodie avec un buzzer passif et le PWM
- Afficher sur un OLED I2C SSD1306 et déboguer le bus
- Logger sur carte microSD en SPI (mode carte)
- Transformer la carte en clavier USB HID avec TinyUSB
Ejemplos de código para esta placa
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython