vectorinterruptavratmega

Handling several AVR Interrupt Vectors


I am trying to handle two AVR interrupt vectors ISR(PCINT1_vect) and ISR(PCINT0_vect). However, only one of them are executed.

Which ISR is executed is dependent upon if function "SonarSensor_init0(void)" or "SonarSensor_init1(void)" is called upon first in the code.

Am I handling multiple ISRs in the wrong way?

I am by the way using Atmega328PB.

    #define F_CPU 16000000UL
    #define USART_BAUDRATE 9600
    #define UBRR_value (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    uint16_t distance1;
    uint16_t distance2;
    
    
    void SonarSensor_init0(void);
    void SonarSensor_init1(void);
    
    
    int main(void)

    {
    
    SonarSensor_init0();
    SonarSensor_init1();
    
    
    while(1)
    {
        sei();
        
        PORTC |= (1 << PINC4);
        _delay_us(10);                                                                  // 10 us trigger. Echo pin is pulled high by control circuit of sonar sensor.
        PORTC &= ~(1<<PINC4);
        
        
        sei();
        
        PORTB |= (1 << PINB0);
        _delay_us(10);                                                                  // 10 us trigger. Echo pin is pulled high by control circuit of sonar sensor.
        PORTB &= ~(1<<PINB0);   
    }
    }


    void SonarSensor_init1(void)

{

    
    
    
    DDRC = 0xFF;                            // Port C all output.
    DDRC &= ~(1<<DDC5);
    
    PORTC |= (1<<PORTC5);                   // Enable pull up on C5 (echo)
    PORTC &= ~(1<<PINC4);                   // Init C4 as low (trigger)
    
    PRR &= ~(1<<PRTIM1);                    // To activate timer1 module
    TCNT1 = 0;                              // Initial timer value
    TCCR1B |= (1<<CS12);                    // Timer without prescaler. Since default clock for atmega328p is 1Mhz period is 1uS
    TCCR1B |= (1<<ICES1);                   // First capture on rising edge

    PCICR = (1<<PCIE1);                     // Enable PCINT[14:8] we use pin C5 which is PCINT13
    PCMSK1 = (1<<PCINT13);                  // Enable C5 interrupt
    

    
    //sei();                                    // Enable global interrrupt


}


void SonarSensor_init0(void)
{
    
    
    DDRB = 0xFF;                            // Port B all output.
    DDRB &= ~(1<<DDB1);
    
    PORTB |= (1<<PORTB1);                   // Enable pull up on B1 (echo)
    PORTB &= ~(1<<PINB0);                   // Init B0 as low (trigger)
    
    PRR &= ~(1<<PRTIM0);                    // To activate timer0 module
    TCNT0 = 0;                              // Initial timer value
    TCCR0B |= (1<<CS00);                    // Timer without prescaler. Since default clock for atmega328p is 1Mhz period is 1uS
    
    
    PCICR = (1<<PCIE0);                     // Enable PCINT[0:7] we use pin B1 which is PCINT1
    PCMSK0 = (1<<PCINT1);                   // Enable B1 interrupt
    
    
    //sei();                                    // Enable global interrrupt

}


ISR(PCINT1_vect) {
    
    if ( (PINC & (1 << PINC5)) == (1 << PINC5))                             // Checks if echo is high
    {
        TCNT1 = 0;      
        PORTB |= (1 << PINB5);                                             // Toggles Debug Led
    }
    
    else
    {
        distance2 = TCNT1/3;                    // Save Timer value
        PORTB &= ~(1 << PINB5);                 // Toggles Debug led
        cli();                                  // Disable global interrupt;
        

    }
}


ISR(PCINT0_vect) {
    
    if ( (PINB & (1 << PINB1)) == (1 << PINB1))                             // Checks if echo is high
    {
        TCNT0 = 0;
        PORTB |= (1 << PINB5);                                              // Toggles debug led
    }
    
    else
    {
        distance1 = TCNT0;                  // Save Timer value
        PORTB &= ~(1 << PINB5);             // Toggles debug led
        cli();

    }
}

Solution

  • It's probably caused by the fact that you have these two conflicting lines in your functions:

    PCICR = (1<<PCIE1);
    
    PCICR = (1<<PCIE0);
    

    When the first line runs, it sets all the bits in PCICR to a particular value. When the second line runs, it sets all of them to a different value, disabling the interrupt that was enabled by the first one. Maybe you should be using |= instead of = so it only modifies the one bit it cares about.