Electronic – AVR SPI target with interrupt

atmegaavrinterruptsslavespi

For a project, I want to have two microcontrollers talk to each other via an SPI interface. I wrote the following code for the target microcontroller:

volatile uint8_t data;

void spi_init_slave (void)
{
 DDRB=(1<<PINB4);               //MISO as OUTPUT
 SPCR=(1<<SPE)|(1<<SPIE);       //Enable SPI && interrupt enable bit
 SPDR=0;
}

uint8_t SPI_SlaveReceive(void)
{      
  /* Wait for reception complete */
  while (!(SPSR & (1<<SPIF)))   ;
  /* Return data register */
  return    SPDR;
}

ISR(SPI_STC_vect)
{
  uint8_t y = SPI_SlaveReceive();
  PORTD = y;
}

int main(void)
{
    DDRD = (1<<PIND0) | (1<<PIND1) | (1<<PIND2) | (1<<PIND3) | (1<<PIND4);
    spi_init_slave();                             //Initialize slave SPI

    sei();
    while(1)
    {

    }
}

The master is sending a number which the target displays using the LEDs attached to port D.

I'm using an Atmega8P for this project.

Best Answer

The most apparent problem I can see is the following line:

SPCR=(1<<SPE)|(1<SPIE);

Is missing a less than sign and should include (1<<SPIE) to enable the SPI interrupt. Note that the current expression (1<SPIE) will be equivalent to the boolean expression (1 < 7) which will result in a value of 1. So that also means at the moment you'll be setting SPR0 for a speed of fosc/16 on the master.