why Interrupt INT2 at atmega32 is not working?

948 Views Asked by At

In my project I am using all external interrupts of atmega32. However, INT2 is not working. The input is read but nothing happens unlike the rest of the INT0 and INT1 external interrupts.

Code

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);
}

So what is wrong and why it's not working ?

1

There are 1 best solutions below

0
On

If you take a look at the ATmega32 Datasheet on Page 51 you can see the priority order of the interrupts

  • 2 $002 INT0 External Interrupt Request 0
  • 3 $004 INT1 External Interrupt Request 1
  • 4 $006 INT2 External Interrupt Request 2

The ATmega architecture does not have a NVI-Controller (like ARM controllers), so the priorisation of the interrupts can not be reorderd. As you can see in the datasheet, the INT0 has the highest priority, the INT2 has the lowest priority for external interrupts. This means that when INT0, INT1 and INT2 are called exactly at the same time, INT0 will be served first, then INT1 will be served and at least INT2 will be served.

If you trigger first INT0 then INT2 and at least INT1 in your example the order the interrupts are getting executed will be:

  • INT0
  • INT1
  • INT2

If you trigger first INT1 then INT2 and then INT0 the order the interrupts are getting executed will be:

  • INT1
  • INT0
  • INT2

A big fault in your example is that you place a delay in your interrupts. PLEASE NEVER DO THIS. An interrupt should be a very short routine and never implement a delay!!!

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!

Notice: If you are using push-buttons on your external interrupts they possible bounce, so the interrupt will be called more than one time!