Multiple External Interrupts on AVR

Discussion in 'Embedded Systems and Microcontrollers' started by donnY_94, Dec 2, 2015.

  1. donnY_94

    Thread Starter New Member

    Dec 2, 2015
    1
    0
    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.
    Code (C):
    1.  
    2. #include <avr/interrupt.h>
    3. #include <avr/io.h>
    4. #include "Led.h"
    5. #include "Interrupt.h"
    6. #include <avr/delay.h>
    7.  
    8. char State_S1 =0;
    9. char State_S2=0;
    10. char State_S3=0;
    11. char State_S4=0;
    12.  
    13. ISR(INT0_vect)      //  External Interrupt 0
    14. {
    15.     State_S1 =1 ;
    16. }
    17.  
    18. ISR(INT6_vect) //External Interrupt 6
    19. {
    20.     State_S2=1;
    21. }
    22.  
    23. ISR(INT7_vect) // External Interrupt 7
    24. {
    25.     State_S3 =1;
    26. }
    27.  
    28. ISR(INT1_vect)  //External Interrupt 1
    29. {
    30.     State_S4 = 1;
    31. }
    32.  
    33. int main(void)
    34.  
    35. {
    36.     Led_init();
    37.     EInterrupt_one();   //External Interrupt one
    38.     //EInterrupt_two(); //External Interrupt two
    39.     //EInterrupt_three(); // External Interrupt three
    40.     //EInterrupt_four(); //External Interrupt four
    41.  
    42.     while(1)
    43.     {
    44.         if(State_S1==1)
    45.         {
    46.             Led_One_On();
    47.             State_S1=0;
    48.             State_S2=0;
    49.         }
    50.     }
    51.  
    52. }

    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:
    Code (C):
    1. void EInterrupt_one(void)
    2. {
    3.     DDRD &= ~(1<<DDD0);   // Pin for Interrupt 0 set to Input
    4.     EIMSK = 1<<INT0; //Enables the Interrupt
    5.     EIFR = 1<<INT0; //Enables Flag
    6.     EICRA = 1<<ISC01; // Triggers Interrupt  0 on falling edges
    7.     sei();
    8. }
    9.  
    10. void EInterrupt_two(void)
    11. {   DDRE &= ~(1<<DDE6);   // Set external Interrupt 6 to Input
    12.     EIMSK = 1<<INT6; //Enables the Interrupt
    13.     //EIFR = 1<<INT6; //Enables Flag
    14.     EICRB = 1<<ISC61;  // Triggers Interrupt 6 on falling edges between two samples
    15.     sei();
    16.     }
    17.  
    18. void EInterrupt_three()
    19. {
    20.     DDRE &= ~(1<<DDE7);   // Pin for Interrupt 7 set to Input
    21.     EIMSK = 1<<INT7; //Enables the Interrupt
    22.     //EIFR = 1<<INT7; //Enables Flag
    23.     EICRB = 1<<ISC71;  // Triggers Interrupt 7 on falling edges
    24.  
    25.     sei();
    26. }
    27.  
    28. void EInterrupt_four()
    29. {
    30.     DDRD &= ~(1<<DDD1);   // Pin for Interrput 1 set to Input
    31.     EIMSK = 1<<INT1; //Enables the Interrupt
    32.     EIFR = 1<<INT1; //Enables Flag
    33.     EICRA = 1<<ISC11;  // Triggers Interrupt 1 for falling edges
    34.     sei();
    35.  
    36. }
    37.  
    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: Dec 2, 2015
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    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: Dec 2, 2015
Loading...