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;
}
}