anti_rebond.c
Mechanical buttons bounce for a few milliseconds: this Zephyr pattern arms a 30 ms timer on each edge and only validates the press if the button is still active after the delay. Bounces never cause double counts.
Hardware
An nRF52833-DK board (Nordic, nRF52833 Cortex-M4F SoC, BLE 5) powered over USB: 4 LEDs on P0.13-P0.16 (active-low) and 4 buttons on P0.11, P0.12, P0.24, P0.25 (active-low, internal pull-up must be enabled). The board alone; button sw0 (P0.11 on the DK) and its LED0 are enough to observe the behavior.
Wiring
No wiring. An external button goes between the pin and GND with the pull-up enabled in the devicetree overlay.
How it works
The ISR only reprograms a k_work 30 ms later (k_work_reschedule cancels the previous one). The work runs in thread context: printk, counting, messaging are all fair game.
Running it
Zephyr project: west build -b nrf52833dk/nrf52833 then west flash (on-board J-Link); 115200 serial console on the USB UART connector.
Variants
Move to 50 ms for chunky buttons, count short vs long presses with two delays, or factor the pattern for the DK four buttons.
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;
}