bouton_gpiote.c

nRF52840-MDK (boards.json id: nrf52840-mdk) · File : bouton_gpiote.c · Language : C · Use case : Détecter un appui par interruption GPIOTE

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
  }
}

← Back to the board