🛠 Interruptions GPIO et alarmes matérielles avec le Pico SDK
Objectives
Move away from "polling": on a generic RP2040 board without embedded LEDs or buttons, you want to react instantly to an external event and wake up at a fixed time without blocking the CPU. The RP2040 provides an IO_BANK0 interrupt controller (levels and edges on each GPIO) and a 64-bit timer with 12 hardware alarms for this purpose (RP2040 datasheet). In C (Pico SDK), you will combine both for a clean button implementation: IRQ on the falling edge, debouncing via a delayed alarm, and CPU sleeping in between.
Hardware
- 1 × generic RP2040 board + USB data cable
- 1 × button between GP2 and GND, 1 × LED (with 330 Ω resistor) on GP15
- Pico SDK (C): standard CMake project, target linked with
pico_stdlib pico_time hardware_irq
Complete Code
// 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
}
}
Expected Verification
Each firm press toggles the LED only once: the IRQ captures the edge, the alarm re-checks the state 50 ms later and ignores bounces (the contact vibrates for ~1 ms). Add a printf in the handler (with stdio_init_all) to confirm that __wfi indeed terminates upon the event. On a µA-meter, WFI sleep causes consumption to drop — the datasheet states SLEEP ≈ 1.3 mA at 25 °C, confirmed by the "dodo-meter".
Common Errors
sleep_msor longprintfin the IRQ handler: the handler must be minimal — schedule an alarm, set a flag, handle it elsewhere.- Forgetting
gpio_pull_up: the input floats and triggers bursts of IRQs (interrupt storm, the CPU does nothing else). - Handler not called:
gpio_set_irq_enabled_with_callbackalso enables the IO_BANK0 IRQ at the NVIC — a simplegpio_set_irq_enabledwithout a callback does nothing. - Alarm not repeating: the callback must return
trueto be rescheduled,falsefor a one-shot. - Two cores, same alarms: the 12 hardware alarms are shared and the SDK reserves some for
sleep_ms— for long-term use, create analarm_pool. - Bounce on release ignored: if you also want the rising edge, add
GPIO_IRQ_EDGE_RISEto the mask — a single handler manages both viaevents.
Other tutorials for this board
- 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
Code examples for this board
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython