/*
ATtiny85 External Interrupt Request 0, on INT0 vector 2.
🧠 Register Overview
Register Purpose
GIMSK Enable pin change interrupt (PCIE)
PCMSK Choose which pin(s) can trigger interrupt
GIFR Flag register
sei() Enable global interrupts
📘 Example: Blink LED on INT0 Trigger (PD2)
Trigger on falling edge (button press to GND)
For the ISR, note:
1. You do not pass any parameters to the ISR and do not let it return anything.
2. The ISR should always be kept as short as possible.
3. For some boards, the ISR must be placed before setup(). That’s why I’m doing it this way throughout this post.
4. Global variables that you change in the ISR must be defined with the keyword volatile.
5. Within the ISR, all further interrupts are suspended.
*/
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define LED_PIN PB0
#define BUTTON_PIN PB2 // (INT0)
#define DEBOUNCE_TIME 50 // Debounce time in milliseconds
// ==== START FUNCTIONS =====
void setup_external_interrupt() {
// GIMSK – General Interrupt Mask Register
GIMSK |= (1 << INT0); // Enable pin change interrupt
// MCUCR – MCU Control Register
MCUCR |= (1 << ISC01); // The falling edge of INT0 generates an interrupt request
MCUCR &= ~(1 << ISC00); // (ISC01 = 1, ISC00 = 0)
sei(); // Enable global interrupts
}
bool is_button_pressed(void) {
// Check if button is pressed (logic low)
if (!(PINB & (1 << BUTTON_PIN))) {
_delay_ms(DEBOUNCE_TIME); // Debounce delay
// Check again to confirm stable press
if (!(PINB & (1 << BUTTON_PIN))) {
// Wait for button release to avoid multiple toggles
while (!(PINB & (1 << BUTTON_PIN))) {
_delay_ms(1); // Simple hold loop
}
return true;
}
}
return false;
}
// ==== END FUNCTIONS =====
ISR(INT0_vect) {
if (is_button_pressed()) { // debounce function
PORTB ^= (1 << LED_PIN); // Toggle LED on interrupt
}
}
int main(void) {
DDRB |= (1 << LED_PIN); // Set LED as output
PORTB |= (1 << BUTTON_PIN); // Pull-up resistor on Pb2
setup_external_interrupt();
while (1) {
// Main loop can sleep, or do other work
}
return 0;
}