Единственная переменная, которая изменяется в прерываниях,
определена как volatile. __tiny volatile char IntFlags; // Various interrupt flags
#define ENTER_BTN (1<<3) // -- "Enter" button
#define SETUP_BTN (1<<4) // -- "Setup" button
#define PROG_BTN (1<<5) // -- "Program" button
#define BUTN_MSK (ENTER_BTN | SETUP_BTN | PROG_BTN)
Разбирайтесь
//
// Constant definitions
//
#define BTN_PRESSED (1<<0) // Any button is pressed
#define BTN_AUTO (1<<1) // Auto repeat mode
//
// Static variables
//
static char BtnFlags; // Various flags
static char BtnDebounce; // Debounce counter
//
// ** InitButtons -- the routine initiates button port
//
void InitButtons(void)
{
INPUT_DDR &= ~BUTN_MSK;
INPUT_PULLUP |= BUTN_MSK;
BtnFlags = BtnDebounce = 0;
}
//
// ** ReadBtns -- the function returns the buttons state
//
char ReadBtns(void)
{
return ~INPUT_PORT & BUTN_MSK;
}
//
// ** GetButtons -- the function does button state check,
// and returns 0 if the buttons are not pressed.
//
char GetButtons(void)
{
char _temp;
while (!(IntFlags & BUTTON_BIT));
IntFlags &= ~BUTTON_BIT;
if (IntFlags & TMO_BIT) // Time-out return
return 0; //
if (!(_temp = ReadBtns())) // No button is pressed
{
return BtnFlags = BtnDebounce = 0;
}
TimoutCnt = 0; // Clear time-out counter
if (!(BtnFlags & BTN_PRESSED))
{
BtnFlags |= BTN_PRESSED;
}
else {
if (!(_temp & PROG_BTN))
return 0;
if (!(BtnFlags & BTN_AUTO)) //
{
if (++BtnDebounce < 80)
return 0;
BtnFlags |= BTN_AUTO; // Set auto-repeat flag
}
else {
if (++BtnDebounce < 20)
return 0;
}
BtnDebounce = 0;
}
return _temp;
}