AVR 定时器和硬件中断

AVR Timer and Hardware interrupts

我尝试在第一次检测到硬件中断检测的下降沿时激活定时器,并在运行 8 次后停用定时器。但是当我停止定时器时,硬件中断再次触发并立即启动定时器。

图中蓝色信号可以忽略。紫色信号是 timer1 切换引脚。绿色是硬件中断切换引脚。

它所要做的就是在第一个下降沿触发,然后在一段时间内切换一个引脚。

我的问题是:为什么硬件中断会触发两次?

#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
}

即使禁用它,下降沿也会设置中断标志。这称为“挂起”中断。一旦中断被启用,它的服务例程就会被调用(前提是满足所有其他启用条件)。

您需要在启用中断之前清除此挂起标志。