bouton_gpiote.c
Plutôt que scruter le bouton en boucle, GPIOTE génère une interruption sur front descendant et réveille le CPU : la boucle principale s'endort en WFE entre deux appuis. Le patron économe par défaut sur nRF52840.
Matériel requis
Une carte nRF52840-MDK (Nordic nRF52840, Cortex-M4F @ 64 MHz, 1 Mo flash / 256 Ko RAM, BLE 5 + 802.15.4) avec son debugger intégré, programmée en C sous nRF5 SDK v17 et SoftDevice S140. Bouton entre P0.02 et GND (bouton utilisateur de la MDK) ; LED sur P0.06.
Câblage
Bouton : une patte P0.02, l'autre GND — le pull-up interne suffit. LED embarquée : rien à câbler.
Fonctionnement
GPIOTE surveille le front HITOLO, l'handler ne fait que lever un drapeau (handler court), la boucle traite et bascule la LED. __WFE met le cœur en attente d'événement.
Exécution
Ouvrir l'exemple correspondant du nRF5 SDK v17 (target custom_board), coller ce code dans main.c, compiler avec Segger Embedded Studio ou Makefile gcc, puis programmer via le debugger intégré (flash_nrf.py ou IDE).
Variantes
Ajouter un anti-rebond logiciel (min 50 ms entre deux appuis comptés), ou un appui long via un timer RTC démarré dans l'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
}
}