I'm trying to get a simple interrupt routine to work on an ATMega328P. There's an LED connected to PD6 and a built-in button on PB7. The LED should blink normally until the button is pressed and then go solid for 1.5s before going back to blinking. Here's the code:
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
int main(void)
{
// Enable pull-ups and set pin directions
MCUCR |= (1<<PUD);
PORTD &= ~(1<<PORTD6);
DDRD |= (1<<DDD6);
PORTB |= (1<<PORTB7);
DDRB &= ~(1<<DDB7);
// Enable pin change interrupt
PCICR = 0x01;
PCMSK0 = 0x80;
sei();
while (1)
{
// Blink LED at standard rate
_delay_ms(500);
PORTD ^= (1<<PORTD6);
_delay_ms(500);
PORTD ^= (1<<PORTD6);
}
}
ISR(PCINT0_vect,ISR_BLOCK)
{
PORTD &= ~(1<<PORTD6);
_delay_ms(500);
PORTD |= (1<<PORTD6);
_delay_ms(1500);
PORTD &= ~(1<<PORTD6);
}
The interrupt triggers correctly, however the ISR routine loops twice. I imagine it's some sort of button bounce issue but I'm unfamiliar with how to deal with it. I tried introducing the 500ms delay at the beginning and I've also tried clearing the pin change interrupt flag within the ISR so that it doesn't trigger again but it still does. Thanks in advance for any help!
button_pressedflag and exit. Then put aif (button_pressed) {delay(1000); button_pressed=false;}after you turn the light on in the main loop. In general though, embedded code should avoid delay loops altogether, and replace them with clock checks and/or timer interrupts. - AShelly