bouton_gpiote.c
Instead of polling the button, GPIOTE raises an interrupt on the falling edge and wakes the CPU: the main loop sleeps in WFE between presses. The power-frugal default pattern on the nRF52840.
Hardware
An nRF52840-MDK board (Nordic nRF52840, Cortex-M4F @ 64 MHz, 1 MB flash / 256 KB RAM, BLE 5 + 802.15.4) with onboard debugger, programmed in C with nRF5 SDK v17 and the S140 SoftDevice. Button between P0.02 and GND (the MDK user button); LED on P0.06.
Wiring
Button: one leg to P0.02, the other to GND — the internal pull-up is enough. Onboard LED: nothing to wire.
How it works
GPIOTE watches the HITOLO edge; the handler only raises a flag (short handler), the loop processes and toggles the LED. __WFE parks the core until the next event.
Running it
Open the matching nRF5 SDK v17 example (custom_board target), paste this code into main.c, build with Segger Embedded Studio or the gcc Makefile, then flash through the onboard debugger.
Variants
Add a software debounce (min 50 ms between counted presses), or a long-press via an RTC timer started in the handler.
bouton_gpiote.c
// nRF52840-MDK : bouton sur P0.02 (bouton utilisateur MDK) via GPIOTE.
// L'interruption réveille le CPU : la boucle principale peut dormir (WFE).
#include "nrfx_gpiote.h"
#include "nrfx.h"
#include "boards.h"
#define BTN_PIN 2U // P0.02 sur MDK (RAZ/BTN selon révision)
static volatile bool appui = false;
static void handler(const nrfx_gpiote_evt_data_t *p_data, uintptr_t ctx) {
(void)p_data; (void)ctx;
appui = true; // simple drapeau : le traitement est ailleurs
}
int main(void) {
nrfx_gpiote_pin_config_t cfg = {
.pull = NRF_GPIOTE_PULL_UP, // bouton vers GND
.drive = NRF_GPIOTE_DRIVE_S0S1,
.init = NRF_GPIOTE_INITIAL_VALUE_HIGH,
};
nrfx_gpiote_init();
nrfx_gpiote_output_config_t out = {
.drive = NRF_GPIOTE_DRIVE_S0S1, .pull = NRF_GPIOTE_PULL_DISABLED
};
nrfx_gpiote_output_configure(6, &out, NRF_GPIOTE_TOGGLE); // LED P0.06
nrfx_gpiote_input_configure(BTN_PIN, &cfg, NRF_GPIOTE_POLARITY_HITOLO);
nrfx_gpiote_pin_int_enable(BTN_PIN);
nrfx_gpiote_subscribe_set(BTN_PIN, NRF_GPIOTE_POLARITY_HITOLO);
NVIC_EnableIRQ(GPIOTE_IRQn);
uint32_t nb = 0;
for (;;) {
if (appui) {
appui = false;
nb++;
nrf_gpio_pin_toggle(6); // la LED change d'état à chaque appui
}
__WFE(); // dort jusqu'à la prochaine interruption
}
}