Course contentsShow
← Embedded Systems & Computer Architecture
Lesson 283 of 9364. Peripheral Interfacing and ControlFree lesson

Implementing Hardware Debouncing for Input Signals

Learners will utilize timer-based filtering techniques to ignore mechanical switch noise and ensure clean signal transitions in input capture systems.

In this lesson, you will learn how to use timer-based filtering to eliminate mechanical "chatter" from switch inputs, ensuring your system registers a single clean transition.

The Mechanical Reality

When you press a physical button, the internal metal contacts don't meet perfectly. Instead, they bounce against each other for a few milliseconds, creating a rapid series of high-to-low and low-to-high voltage transitions. If your microcontroller is monitoring these inputs, it might interpret this "chatter" as dozens of rapid button presses rather than one.

The Timer-Based Filtering Solution

To solve this, we implement a filter that ignores any signal changes occurring within a short, predefined "stability window." Instead of responding to the initial edge detection (like we do with standard GPIO interrupts), we use a timer to wait until the signal has settled.

Here is the logic for a typical timer-based debounce:

  1. Detect Initial Edge: A GPIO interrupt triggers on the first transition.
  2. Disable Further Interrupts: Temporarily mask the interrupt to prevent re-triggering.
  3. Start Timer: Configure a hardware timer to expire after the debounce interval (e.g., 20ms).
  4. Verify State: When the timer interrupt fires, check the GPIO input pin again.
  5. Accept Transition: If the pin state remains stable, register the event. If it has reverted (due to a bounce), ignore the event and reset the system to watch for the next transition.
void GPIO_Interrupt_Handler() {
    // 1. Disable interrupt to ignore noise
    Disable_Interrupt(BUTTON_PIN);
    
    // 2. Start a 20ms timer for stability check
    Start_Timer(20ms);
}

void Timer_Callback() {
    // 3. Verify the signal is still in the active state
    if (Read_GPIO(BUTTON_PIN) == PRESSED_STATE) {
        Perform_Action();
    }
    
    // 4. Clear flag and re-enable interrupt for next press
    Clear_Timer_Flag();
    Enable_Interrupt(BUTTON_PIN);
}

By leveraging the precision of hardware timers, we move the burden of "cleaning up" the signal away from the CPU's main loop and into a reliable, asynchronous peripheral sequence. This ensures that your system only reacts to intentional user input, not the mechanical imperfections of the switch.

Key Takeaway: By delaying the processing of an input signal using a timer-based stability window, you effectively filter out high-frequency mechanical noise to ensure accurate, single-event detection.