led_blink.c
El hola mundo de bajo nivel del nRF52840: el LED parpadea escribiendo directamente en los registros GPIO, sin SDK ni configuración de reloj. Entender OUTSET/OUTCLR y PIN_CNF es la base de todo lo demás en los chips Nordic.
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. nRF52840-MDK alimentada por USB; LED de usuario P0.06 (o LED externa + 330 Ω en un pin libre).
Cableado
Ninguno para el LED integrado. Externo: ánodo mediante 330 Ω al pin elegido, cátodo a GND (los pines toleran 3,3 V).
Funcionamiento
PIN_CNF configura dirección y drive; OUTSET/OUTCLR ponen el pin a 1/0 de forma atómica, sin lectura-modificación-escritura. La espera es un bucle NOP calibrado a ojo.
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
Sustituir la espera por el temporizador RTC para dormir entre parpadeos (versión de bajo consumo), o alternar dos LED.
led_blink.c
// nRF52840-MDK : clignotement LED en accès direct aux registres (zéro SDK).
// LED utilisateur MDK : P0.06 (vérifier la sérigraphie de votre révision).
#include <stdint.h>
#include "nrf.h"
#define LED_PIN 6 // P0.06 sur MDK
#define PORT0_BASE 0x50000000UL
typedef struct { volatile uint32_t t[12]; } NRF_GPIO_Type;
#define NRF_GPIO0 ((NRF_GPIO_Type *)PORT0_BASE)
static void delay_ms(uint32_t ms) { // boucle d'attente grossière
for (volatile uint32_t i = 0; i < ms * 8000UL; i++) { __NOP(); }
}
int main(void) {
// Configure P0.06 en sortie push-pull, drive standard.
NRF_GPIO->PIN_CNF[LED_PIN] =
(GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) |
(GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos);
for (;;) {
NRF_GPIO->OUTSET = (1UL << LED_PIN); // LED ON (cathode vers GND)
delay_ms(500);
NRF_GPIO->OUTCLR = (1UL << LED_PIN); // LED OFF
delay_ms(500);
}
}