Course contentsShow
← Embedded Systems & Computer Architecture
Lesson 251 of 9363. Microcontroller Fundamentals and Bare-Metal CFree lesson

Debouncing Mechanical Switches Using Input Polling

Implement a software-based debouncing algorithm to reliably read mechanical switch states while ignoring transient signal noise during transitions.

In this lesson, you will learn how to distinguish a genuine user button press from the chaotic, noisy electrical signals generated by mechanical switches.

The Problem: Mechanical Bounce

When you press a physical button, the internal metal contacts don't meet cleanly. Instead, they strike each other, bounce slightly, and settle over a period of 5–20 milliseconds. To a high-speed microcontroller reading the GPIO pin, this "bouncing" looks like dozens of rapid button presses rather than one single click. If you don't address this, your firmware will trigger the same action multiple times per physical press.

The Solution: Software Debouncing

We can ignore this noise using a simple polling strategy: The Wait-and-Verify method. Instead of trusting the input the moment we see a change, we wait until the signal stabilizes.

Since we are using polling, we check the GPIO data register periodically. If we detect a transition (e.g., from high to low), we don’t immediately accept it. We wait for a short duration—roughly 25ms—and check the pin again. If the pin is still low after that duration, we treat the press as valid.

Implementation Example

We can implement this by combining a polling loop with a simple delay:

#define DEBOUNCE_DELAY_MS 25

bool read_button_debounced(void) {
    // 1. Poll for initial state change
    if (!(GPIO_PORT_IN & BUTTON_PIN)) {
        // 2. Wait for the mechanical chatter to die down
        software_delay_ms(DEBOUNCE_DELAY_MS);
        
        // 3. Confirm the state is still pressed
        if (!(GPIO_PORT_IN & BUTTON_PIN)) {
            return true; // Valid press confirmed
        }
    }
    return false;
}

By introducing this small timing gap, you act as a filter. Any signal jitter faster than your DEBOUNCE_DELAY_MS is discarded, ensuring your system only reacts to the intentional intent of the user. This approach is highly efficient for bare-metal systems because it requires no complex interrupts or external hardware, relying purely on the logic of your polling loop.

Key Takeaway: Mechanical switch bounce is a transient physical reality that must be mitigated by waiting for a signal to stabilize before confirming a state change in your firmware.