bouton_gpiote.c

nRF52840-MDK (id boards.json: nrf52840-mdk) · Archivo : bouton_gpiote.c · Lenguaje : C · Uso : Détecter un appui par interruption GPIOTE

En lugar de escrutar el botón en bucle, GPIOTE genera una interrupción por flanco de bajada y despierta la CPU: el bucle principal duerme en WFE entre pulsaciones. El patrón económico por defecto en nRF52840.

Hardware

Una placa nRF52840-MDK (Nordic nRF52840, Cortex-M4F @ 64 MHz, 1 MB flash / 256 KB RAM, BLE 5 + 802.15.4) con depurador integrado, programada en C con nRF5 SDK v17 y SoftDevice S140. Botón entre P0.02 y GND (botón de usuario de la MDK); LED en P0.06.

Cableado

Botón: una pata a P0.02, la otra a GND: la resistencia de tirada interna basta. LED integrado: nada que cablear.

Funcionamiento

GPIOTE vigila el flanco HITOLO; el handler solo levanta un flag (handler corto), el bucle lo procesa y alterna el LED. __WFE aparca el núcleo hasta el próximo evento.

Ejecución

Abre el ejemplo equivalente del nRF5 SDK v17 (objetivo custom_board), pega este código en main.c, compila con Segger Embedded Studio o el Makefile de gcc y programa por el depurador integrado.

Variantes

Añadir antirrebote software (mínimo 50 ms entre pulsaciones contadas), o pulsación larga con un temporizador RTC iniciado en el 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
  }
}

← Volver a la ficha