anti_rebond.c
Los botones mecánicos rebotan unos milisegundos: este patrón Zephyr arma un timer de 30 ms en cada flanco y solo valida la pulsación si el botón sigue activo tras el retardo. Los rebotes nunca provocan doble conteo.
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). Solo la placa; el botón sw0 (P0.11 en el DK) y su LED0 bastan para observar el comportamiento.
Cableado
Sin cableado. Un botón externo va entre el pin y GND con el pull-up activado en el overlay devicetree.
Funcionamiento
La ISR solo reprograma un k_work 30 ms después (k_work_reschedule cancela el anterior). El trabajo corre en contexto de hilo: printk, contar o mandar mensajes valen.
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
Pasar a 50 ms para botones robustos, contar pulsaciones cortas/largas con dos retardos, o factorizar el patrón para los cuatro botones del DK.
anti_rebond.c
/* Anti-rebond : appui valide si le bouton est encore actif
* 30 ms apres le front (k_work_reschedule). */
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
static const struct gpio_dt_spec btn =
GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
static const struct gpio_dt_spec led =
GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
static struct gpio_callback cb_data;
static struct k_work travail;
static void valide(struct k_work *w)
{
ARG_UNUSED(w);
if (gpio_pin_get_dt(&btn) == 1) {
gpio_pin_toggle_dt(&led);
printk("Appui valide\n");
}
}
static void sur_front(const struct device *port,
struct gpio_callback *cb, uint32_t pins)
{
ARG_UNUSED(port); ARG_UNUSED(cb); ARG_UNUSED(pins);
k_work_reschedule(&travail, K_MSEC(30));
}
int main(void)
{
k_work_init(&travail, valide);
gpio_pin_configure_dt(&led, GPIO_OUTPUT_INACTIVE);
gpio_pin_configure_dt(&btn, GPIO_PULL_UP);
gpio_pin_interrupt_configure_dt(&btn, GPIO_INT_EDGE_BOTH);
gpio_init_callback(&cb_data, sur_front, BIT(btn.pin));
gpio_add_callback(btn.port, &cb_data);
while (1) {
k_msleep(100);
}
return 0;
}