Electronic – Unable to set Pin Change Interrupt on ATmega328p

atmega328pavrinterruptsregister

so I am working on learning some AVR programming with the ATmega328p. I am trying to set up a pin change interrupt and this is the code I am running. However, the interrupt never seems to trigger. Is there anything I am doing wrong?

Is there some way I can test this outside of using a board, like in simulation? I am using Atmel Studio.

Thanks!

#include <avr/io.h>

#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>

#define ON_B0 PORTB |= (1 << PORTB0)
#define OFF_B0 PORTB &= ~(1 << PORTB0)
#define TOGGLE_B0 PINB |= (1 << PINB0)

ISR(PCINT1_vect)
{
    // Check if pin B1 is low)
    if ( !( PINB & (1 << PINB1) ) )
    {
        ON_B0;
    }
    else
    {
        OFF_B0;
    }   
}

int main(void)
{
    DDRB |= ( 1 << DDB0 );
    DDRB &= ~( 1 << DDB1 );

    PCMSK0 |= ( 1 << PCINT1);
    PCICR |= ( 1 << PCIE0);

    sei();


    while (1) 
    {
        PORTB |= ( 1 << PORTB1);
    }
}

Best Answer

The problem is you have an ISR on the PCINT1 vector, but the vector for PORTB pin changes is PCINT0. Uninitialized vectors jump to address 0, so the MCU resets when a pin change interrupt occurs on PORTB.

This is an easy mistake to make because PCINT1 is the designation of pin PB1 for pin change, and also the name of the vector for pin change interrupts on PORTC (thanks Atmel!).

You need to change ISR(PCINT1_vect) to ISR(PCINT0_vect).

Is there some way I can test this outside of using a board, like in simulation?

Yes (this is how I found the error in your code). In AVR simulator you can simulate a pin change by clicking on the pin to toggle it, then follow the resulting code execution with 'step into' (F11). View disassembler to step through the machine code one instruction at a time.

enter image description here