ble_bouton.c
La placa se vuelve periférico BLE: el servicio 0xFFF0 expone una característica notify cuyo valor sigue al botón sw0. Un móvil (app nRF Connect) ve cada pulsación en tiempo real. La base de todo mando o sensor inalámbrico.
Hardware
Una placa nRF52833-DK (Nordic, SoC nRF52833 Cortex-M4F, BLE 5) alimentada por USB: 4 LED en P0.13-P0.16 (activos a nivel bajo) y 4 botones en P0.11, P0.12, P0.24, P0.25 (activos a bajo, pull-up interno a activar). La placa sola por el lado hardware; un móvil con nRF Connect o LightBlue por el lado cliente.
Cableado
Sin cableado, la antena va embarcada (el MDK tiene su antena de cerámica; el DK tiene la del módulo).
Funcionamiento
BT_GATT_SERVICE_DEFINE declara el GATT estáticamente; bt_le_adv_start difunde el nombre; bt_gatt_notify envía el valor a los clientes suscritos vía el CCC. Requiere Kconfig BT=y.
Ejecución
Proyecto Zephyr: west build -b nrf52833dk/nrf52833 y luego west flash (J-Link embarcado); consola serie 115200 en el conector USB UART.
Variantes
Añadir pairing/bonding (CONFIG_BT_SMP), enviar medidas periódicas del sensor, o pasar al servicio estándar NUS para una terminal serie BLE.
ble_bouton.c
/* Périphérique BLE : service custom avec caractéristique notify.
* Kconfig : CONFIG_BT=y, CONFIG_BT_PERIPHERAL=y (nRF Connect SDK). */
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/drivers/gpio.h>
static const struct gpio_dt_spec btn =
GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
static uint8_t etat_btn;
/* Service 0xFFF0, caractéristique notify 0xFFF1 (UUID 16 bits maison) */
BT_GATT_SERVICE_DEFINE(svc_bouton,
BT_GATT_PRIMARY_SERVICE(BT_UUID16_DECLARE(0xFFF0)),
BT_GATT_CHARACTERISTIC(BT_UUID16_DECLARE(0xFFF1),
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ,
NULL, NULL, &etat_btn),
BT_GATT_CCC(NULL, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
);
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME,
sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};
int main(void)
{
gpio_pin_configure_dt(&btn, GPIO_PULL_UP);
bt_enable(NULL);
bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0);
int dernier = -1;
while (1) {
int e = gpio_pin_get_dt(&btn);
if (e != dernier) {
dernier = e;
etat_btn = e;
bt_gatt_notify(NULL, &svc_bouton.attrs[1],
&etat_btn, sizeof(etat_btn));
}
k_msleep(50);
}
return 0;
}