arduinoavrinterrupt-handlingatmegaavrdude

ATMEGA328p interrupt not working when using avrdude


I'm trying to use light a led placed in PB0, when detecting the INT1 interrupt on an atmega328p without an external ocilator. I'm using avrdude to upload the code to the micro. This is the code:

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
    
int main(void)
{
    
  cli();
  UCSR0B = 0;

   
  DDRB  |= 0b00000001;
  DDRD  &= 0b11111101;
  EICRA |= 0b00001111;
  EIMSK |= 0b00000010;
  EIMSK &= 0b11111110;
  sei();
        
  while(1)
  {
    PORTB &= 0b11111110;
    
  }
}
    
ISR(INT1_vect)
{
  PORTB |= 0b00000001;
  _delay_ms(1000);
}

But doesn't work. The LED stays at a medium-light flare and does nothing. But when uploading the same code through the Arduino IDE it works as it has to:

int main()
{
  cli();
  DDRB  |= 0b00000001;
  DDRD  &= 0b11111101;
  EICRA |= 0b00001111;
  EIMSK |= 0b00000010;
  EIMSK &= 0b11111110;
  sei();
  
  while(1)
  {
    PORTB &= 0b11111110;
  }
}

ISR(INT1_vect)
{
  PORTB |= 0b00000001;
  _delay_ms(1000);
}

I can't understand anything.


Solution

  • Ok i found some things in your code that should not be there.

    ISR(INT1_vect)
    {
      PORTB |= 0b00000001;
      // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      // Please never use a delay function in an ISR
      // ISRs should be as short as possible
      // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      _delay_ms(1000);
    }
    

    if you don´t need the UCSR0B register don´t paste it in your code! The question now is where are you awaiting the interrupt. It seems to be on PORTD on PIND3 (from the Datasheet)?

    This makes no sense

    DDRD  &= 0b11111101;
    

    Cause DDRD is initially setup to 0b00000000 after reset! So you are trying to do this:

    // DDRD -> 0b00000000 (Current)
    //       & 0b11111101
    //       ------------
    //         0b00000000 (Result)
    

    But the PORTD configuration seems to be correct PIND3is setup as input. The question now is do you need the internal pullup resistor?

    // DDRB  |= 0b00000001;
    // DDRD  &= 0b11111101;
    
    // May has a better readability?
    DDRB = 0b00000001;
    DDRD = 0b00000000;
    
    // Enable internal pullup on PIND3?
    PORTD |= 0b00001000;
    

    The LED seems to be connected on PORTB PINB0? So everything is fine. Lets checkup the interrupt configuration:

    // You are configuring both INT1 and INT 0!!!
    // EICRA |= 0b00001111;
    // EICRA |= (1<<ISC11) | (1<<ISC10) | (1<<ISC01) | (1<<ISC00);
    //          (-------  INT1 -------)   (-------- INT0 -------)
    
    // For testing purpose check this
    EICRA |= (1<<ISC10); // Enter interrupt on any logical change
    
    // EIMSK |= 0b00000010;
    EIMSK |= (1<<INT1);  // Enable interrupt 1
    

    Please try to work with the Bitnames in the register (better readability)!

    So the whole code should look like:

    #define F_CPU 8000000UL
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
        
    int main(void)
    {
      // cli();  // Not necessary (after reset interrups are locked)
    
      DDRB = 0b00000001;    // PINB0 as output
      DDRD = 0b00000000;    // All Pins are input
    
      // Enable internal pullup on PIND3?
      // PORTD |= 0b00001000;
    
      EICRA |= (1<<ISC10);  // Jump to INT1 on every logical change
      EIMSK |= (1<<INT1);   // Enable INT1
    
      sei();                // Enable interrupts globally
      
      while(1)
      {
      }
    }
        
    ISR(INT1_vect)
    {
      // Maybe for testing purpose you want to toggle the pin?
      PORTB ^= 0b00000001;
    }
    

    Please give me feedback if that solved your problem?