-1

在我的项目中,我使用atmega32. 但是,INT2不工作。读取输入,但没有发生与其余中断INT0INT1外部中断不同的情况。

代码

int main(void) 
{
    DDRC = 0xFF;                                                                           
    
    GICR|= (1 << INT0) | (1 << INT1) | (1 << INT2);
    GICR|= (1 << INT2); 
    MCUCR |= (1 << ISC10) | (1 << ISC11)|(1 << ISC00) | (1 << ISC01);
    MCUCSR |= (1 << ISC2);  //Activating all interrupt to react to rising edges
    sei(); 

    while(1)    
    {     
        
    }    
    return 0;
}

ISR(INT0_vect)
{
    PORTC ^= (1 << PC3); 
    _delay_ms(2000);
    PORTC ^= (1 << PC3);
}

ISR(INT1_vect) 
{
    PORTC ^= (1 << PC0);
    _delay_ms(2000);
     PORTC ^= (1 << PC0);
}

ISR(INT2_vect)
{
    PORTC ^= (1 << PC1); 
    _delay_ms(2000);
    PORTC ^= (1 << PC1);
}

那么有什么问题,为什么它不起作用?

4

1 回答 1

0

如果您查看第 51 页的 ATmega32数据表,您可以看到中断的优先级顺序

  • 2 $002 INT0 外部中断请求 0
  • 3 $004 INT1 外部中断请求 1
  • 4 $006 INT2 外部中断请求 2

ATmega 架构没有 NVI 控制器(如 ARM 控制器),因此无法重新排序中断的优先级。正如您在数据表中看到的,INT0 的优先级最高,INT2 的外部中断优先级最低。这意味着当 INT0、INT1 和 INT2 恰好同时被调用时,将首先服务于 INT0,然后再服务于 INT1,并且至少会服务于 INT2。

如果您先触发 INT0,然后触发 INT2,并且在您的示例中至少触发 INT1,则执行中断的顺序将是:

  • INT0
  • INT1
  • INT2

如果您先触发 INT1,然后触发 INT2,然后触发 INT0,则执行中断的顺序将是:

  • INT1
  • INT0
  • INT2

您的示例中的一个大错误是您在中断中设置了延迟。请永远不要这样做。中断应该是一个非常短的例程,永远不要实现延迟!!!

ISR(INT0_vect)
{
  PORTC ^= (1 << PC3);
}

// ...
GICR|= (1 << INT0) | (1 << INT1) | (1 << INT2);
// GICR|= (1 << INT2); // This is not necessary

//...
MCUCSR |= (1 << ISC2);  // Does not activate all interrupts! It activates INT2 to detect a rising edge!

注意:如果您在外部中断上使用按钮,它们可能会反弹,因此中断将被多次调用!

于 2020-08-01T18:38:55.093 回答