bouton_gpiote.c
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
}
}