I try to activate a timer at the first detection on falling edge of hardware interrupt detection and to deactivate the timer after 8 runs. But when I stop the timer, the hardware interrupt triggers again and starts the timer immediately.
In the image you can ignore the blue signal. The purple signal is timer1 toggling the pin. Green is hardware interrupt toggling the pin.
All it has to do is trigger at the first falling edge, then toggling a pin in a period of time.
My question is: why does hardware interrupts trigger twice?
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile int cnt = 0;
uint8_t data[8];
int main(void)
{
// TIMER 1
DDRB |= (1 << PORTB0); // Set LED as output
DDRB |= (1 << PORTB1); // Set LED as output
DDRB |= (1 << PORTB2); // Set LED as output
DDRD &= ~(1 << PORTD2); // Set LED as INPUT
PORTD |= (1 << PORTD2); // PULLUP resistor
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
TIMSK1 &= ~(1 << OCIE1A); // Disable CTC interrupt
//TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt
OCR1A = 1200; // Set CTC compare value to 15873Hz at 16MHz AVR clock, with a prescaler of 1
//TCNT0 = 0;
TCCR1B |= ((1 << CS10)); // Start timer at Fcpu/1
// Interrupt
EICRA |= (1 << ISC01) | (1 << ISC11); //ENABLE INT0 and INT1 ON falling EDGE
EIMSK |= (1 << INT0); //ENABLE INT0
EIMSK |= (1 << INT1); //ENABLE INT0
sei(); // Enable global interrupts
while (1)
{
}
}
ISR(TIMER1_COMPA_vect)
{
cnt = cnt + 1;
PORTB ^= (1 << PORTB0); // D8
if (cnt > 7)
{
TIMSK1 &= ~(1 << OCIE1A); // stop CTC interrupt
EIMSK |= (1 << INT0); //Enable INT0
EIMSK |= (1 << INT1); //Enable INT0
return;
}
}
ISR(INT0_vect) //External interrupt_zero ISR
{
EIMSK &= ~(1 << INT0); //Disable INT0
PORTB ^= (1 << PORTB2); // Toggle the LED
TCNT1 = 0;
cnt = 0;
TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt
}
ISR(INT1_vect) //External interrupt_zero ISR
{
PORTB ^= (1 << PORTB2); // Toggle the LED
EIMSK &= ~(1 << INT1); //Disable INT0
TCNT1 = 0;
cnt = 0;
TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt
}
The falling edge sets the interrupt flag even if you disable it. This is called a "pending" interrupt. As soon as the interrupt is enabled, its service routine is called (given that all other enabling conditions are met).
You need to clear this pending flag before you enable the interrupt.