Skip to content

Instantly share code, notes, and snippets.

@robertcasanova
Created August 20, 2014 07:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save robertcasanova/42069c755fbb0826192c to your computer and use it in GitHub Desktop.
Save robertcasanova/42069c755fbb0826192c to your computer and use it in GitHub Desktop.
Button Click & Hold (AVR)
#define BTN_DEBOUCE 20 //ms
ISR(INT0_vect) {
uint16_t timer = 0;
while(bit_is_clear(PIND, PD2)) { // button hold down
timer++; // count how long button is pressed
_delay_ms(1);
}
if(timer > BTN_DEBOUCE) { // software debouncing button
if(timer < 500UL) {//unsigned long
//single click
printString("single click");
} else {
//button hold
printString("hold down");
}
}
}
void initInterrupt0(void) {
GIMSK |= (1 << INT0); // general interrupt mask register -> enable interrupt on INT0
MCUCR &= ~(1 << ISC00); // trigger interrupt on falling edge
MCUCR |= (1 << ISC01); // trigger interrupt on falling edge
sei(); // set interrupt enable bit
}
@Paul595
Copy link

Paul595 commented May 17, 2021

Did this solution work for you?
I am asking because I don't see the use case as you block all other operations as the user is pressing the button.
Have you considered doing it with a 1ms Timer that counts for how long the button is pressed?

@robertcasanova
Copy link
Author

Hi, this code is quite old and you are right, it's blocking CPU. Since the same interrupt routine is called both when you first press and then when you release the button you can know how much time is passed between the two (of course you need debouncing to be sure you are checking the right button state).

@kpierzynski
Copy link

Hello. Never use delay function in ISR. It is really bad practice, that can cause hard to debug problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment