🛠 Interruptions GPIO et alarmes matérielles avec le Pico SDK
Objectifs
Sortir du « polling » : sur une carte RP2040 générique sans LED ni bouton embarqués, tu veux réagir instantanément à un événement extérieur et te réveiller à heure fixe sans bloquer le CPU. Le RP2040 fournit pour ça un contrôleur d'interruptions IO_BANK0 (niveaux et fronts sur chaque GPIO) et un timer 64 bits à 12 alarmes matérielles (datasheet RP2040). En C (Pico SDK), tu vas combiner les deux pour un bouton propre : IRQ sur le front descendant, anti-rebond par alarme différée, CPU endormi entre les deux.
Matériel
- 1 × carte RP2040 générique + câble USB data
- 1 × bouton entre GP2 et GND, 1 × LED (avec résistance 330 Ω) sur GP15
- Pico SDK (C) : projet CMake standard, cible liée avec
pico_stdlib pico_time hardware_irq
Code complet
// 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
}
}
Vérification attendue
Chaque appui franc bascule la LED une seule fois : l'IRQ capture le front, l'alarme re-vérifie l'état 50 ms plus tard et ignore les rebonds (le contact vibre ~1 ms). Ajoute un printf dans le handler (avec stdio_init_all) pour confirmer que le __wfi se termine bien sur l'événement. Sur un µA-mètre, le sommeil WFI fait chuter la consommation — la datasheet annonce SLEEP ≈ 1,3 mA à 25 °C, dodo-mètre à l'appui.
Erreurs fréquentes
sleep_msouprintflong dans le handler d'IRQ : le handler doit être minimal — planifie une alarme, poste un drapeau, traite ailleurs.- Oublier
gpio_pull_up: l'entrée flotte et déclenche des IRQ en rafale (tempête d'interruptions, le CPU ne fait plus rien d'autre). - Handler non appelé :
gpio_set_irq_enabled_with_callbackactive aussi l'IRQ IO_BANK0 au NVIC — un simplegpio_set_irq_enabledsans callback ne fait rien. - Alarme qui ne se répète pas : le callback doit retourner
truepour être reprogrammé,falsepour un one-shot. - Deux cœurs, mêmes alarmes : les 12 alarmes matérielles sont partagées et le SDK en réserve pour
sleep_ms— pour du long terme, crée unealarm_pool. - Rebond sur le relâchement ignoré : si tu veux aussi le front montant, ajoute
GPIO_IRQ_EDGE_RISEau masque — un handler unique gère les deux viaevents.
Autres tutoriels pour cette carte
- 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
Exemples de code pour cette carte
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython