Multiple External Interrupts on AVR

Thread Starter

donnY_94

Joined Dec 2, 2015
1
Dear Community,

I am trying to connect four sensor to an AT90CAN128 uC. These Sensors are conencted to the external Interrupt pins. I have created a interrupt.h file where I have declared all these Pins as Input and also enabled all these External Interrupts set them to trigger on falling edges.

For each external interrupt I have declared an ISR.

When The first Sensor triggers the LED goes on, however this is only the case when all the other external Interrupts are not initialized in the main program. To avoid confusion with this question I'll post some code in order to make it more clear.
C:
#include <avr/interrupt.h>
#include <avr/io.h>
#include "Led.h"
#include "Interrupt.h"
#include <avr/delay.h>

char State_S1 =0;
char State_S2=0;
char State_S3=0;
char State_S4=0;

ISR(INT0_vect)      //  External Interrupt 0
{
    State_S1 =1 ;
}

ISR(INT6_vect) //External Interrupt 6
{
    State_S2=1;
}

ISR(INT7_vect) // External Interrupt 7
{
    State_S3 =1;
}

ISR(INT1_vect)  //External Interrupt 1
{
    State_S4 = 1;
}

int main(void)

{
    Led_init();
    EInterrupt_one();   //External Interrupt one
    //EInterrupt_two(); //External Interrupt two
    //EInterrupt_three(); // External Interrupt three
    //EInterrupt_four(); //External Interrupt four

    while(1)
    {
        if(State_S1==1)
        {
            Led_One_On();
            State_S1=0;
            State_S2=0;
        }
    }

}

Dont get confused by the names, i named these functions one, two t,hree and four to help me organize them better. As you can see i have commented these interrupts out
//EInterrupt_two(); //External Interrupt two
//EInterrupt_three(); // External Interrupt three
//EInterrupt_four(); //External Interrupt four

And the program works fine when the Interrupt occurs, however when i activate any of them for example
EInterrupt_one(); //External Interrupt one
EInterrupt_two(); //External Interrupt two
//EInterrupt_three(); // External Interrupt three
//EInterrupt_four(); //External Interrupt four

It wont work.

Here is how i have declared these Interrupts:
C:
void EInterrupt_one(void)
{
    DDRD &= ~(1<<DDD0);   // Pin for Interrupt 0 set to Input
    EIMSK = 1<<INT0; //Enables the Interrupt
    EIFR = 1<<INT0; //Enables Flag
    EICRA = 1<<ISC01; // Triggers Interrupt  0 on falling edges
    sei();
}

void EInterrupt_two(void)
{   DDRE &= ~(1<<DDE6);   // Set external Interrupt 6 to Input
    EIMSK = 1<<INT6; //Enables the Interrupt
    //EIFR = 1<<INT6; //Enables Flag
    EICRB = 1<<ISC61;  // Triggers Interrupt 6 on falling edges between two samples
    sei();
    }

void EInterrupt_three()
{
    DDRE &= ~(1<<DDE7);   // Pin for Interrupt 7 set to Input
    EIMSK = 1<<INT7; //Enables the Interrupt
    //EIFR = 1<<INT7; //Enables Flag
    EICRB = 1<<ISC71;  // Triggers Interrupt 7 on falling edges

    sei();
}

void EInterrupt_four()
{
    DDRD &= ~(1<<DDD1);   // Pin for Interrput 1 set to Input
    EIMSK = 1<<INT1; //Enables the Interrupt
    EIFR = 1<<INT1; //Enables Flag
    EICRA = 1<<ISC11;  // Triggers Interrupt 1 for falling edges
    sei();

}
I hope anyone can explain me how multiple External Interrupts work. I have searched everywhere but could not find a propper answer.

Thank you very much.

Kind Regards,

Don

Mod EDIT: Added code tags to make code easier to read.
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,719
I don't know much about AVR but a general procedure to set up multiple interrupt sources is:

Disable global interrupts - even after reset using cli();
For each peripheral / external interrupt source, configure whatever you need to set up the interrupt (edge, load timers etc etc).
Clear the interrupt flag associated with the interrupt source then..
Enable the peripherial/external interrupt (NOT the global interrupt enable - yet)
When ALL peripherals have been set up and any pending interrupt flags cleared, then and only then enable the global interrupt.

You appear to be enabling global interrupt in every peripheral / external interrupt config routine. The key is to have everything set up and happy before turning it loose with sei(). Don't forget the stack pointer.

It wouldn't hurt to examine the assembler code that your init functions generates to see if your C syntax is flipping the correct bit(s) in the control registers.

Finally, the AVR datasheet calls out sei / cli with an underscore i.e. _SEI() . That usually means its a macro which expands to inline code. Without the underscore, its usually a function which gets called. Check your compiler docs and use the macro version when setting up. I personally don't like calls when controlling interrupts.

Good luck.

EDIT: @donnY_94 Looking at it one more time..
//EIFR = 1<<INT6; //Enables Flag - The operator should be |= so you don't clear the other bits, yes?
 
Last edited:
Top