Button Scan Routine with Release Detection for MCU Sleep Control

This button scanning routine is designed to manage a power-saving feature: a long press of the button triggers a shutdown of all MCU peripherals (simulated by turning off an LED), but the actual sleep mode is only entered after the button is released. This prevents accidental wake-ups by ensuring the user intentional completes the press-and-release sequence.

To implement reliable button handling, we consider the following key states:

  • Initial state: button is released.
  • Transition from released to pressed.
  • Button held down (may trigger continuous or single action).
  • Transition from pressed to released.
  • Button remains released.

The following variables support debouncing and state tracking:

  • release_count: increments when the button is not pressed; used for release debouncing.
  • press_count: increments while the button is pressed; used for press debouncing.
  • key_state_locked: prevents re-triggering during a sustained press.
  • key_confirmed_pressed: set to 1 once a valid press is detected.
  • execute_action: flag indicating that a long press has been recognized.
  • key_released_confirmed: set to 1 only after a valid press is followed by a clean release.

The core scanning logic is implemented as follows:

void KeyScan(void)
{
    if (!KEY1) // Button is pressed (active low)
    {
        release_count = 0;
        if (!key_state_locked)
        {
            press_count++;
            if (press_count >= 1000) // ~1 second hold (assuming 1ms tick)
            {
                key_state_locked = 1;
                key_confirmed_pressed = 1;
                execute_action = 1;
            }
        }
    }
    else // Button is released
    {
        if (key_confirmed_pressed)
        {
            release_count++;
            if (release_count >= 50) // ~50ms release debounce
            {
                key_confirmed_pressed = 0;
                key_released_confirmed = 1;
            }
        }
        press_count = 0;
        key_state_locked = 0;
    }
}

In the main loop, the system responds to these flags:

while (1)
{
    delay_ms(1);
    KeyScan();

    if (execute_action)
    {
        // Simulate "soft shutdown": e.g., turn off indicator LED on P20
        P20 = 1;
    }

    if (key_released_confirmed)
    {
        // Enable wakeup interrupt
        enable_button_wakeup_interrupt();
        // Enter true sleep mode
        enter_sleep_mode();
        // Clear flag after use
        key_released_confirmed = 0;
    }
}

Tags: MCU Embedded C button debouncing low-power mode gpio

Posted on Fri, 15 May 2026 11:36:59 +0000 by stylefrog