AVR esclavo SPI con interrupción

2

Para un proyecto, quiero que dos microcontroladores hablen entre sí a través de una interfaz SPI. Escribí el siguiente código para el esclavo:

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)
    {

    }
}

El maestro está enviando un número que el esclavo muestra usando los LED conectados al puerto D. Estoy usando un Atmega8P para este proyecto.

    
pregunta BoboProg

4 respuestas

5

El problema más aparente que puedo ver es la siguiente línea:

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

Falta un signo menos que y debe incluir (1<<SPIE) para habilitar la interrupción SPI. Tenga en cuenta que la expresión actual (1<SPIE) será equivalente a la expresión booleana (1 < 7) que dará como resultado un valor de 1. Así que eso también significa que en el momento estará configurando SPR0 para una velocidad de fosc / 16 en el maestro.

    
respondido por el PeterJ
2

Sé que este tiene un año de antigüedad, pero pensé que solo señalaría que cuando intenté implementar su código, la rutina de interrupción solo activaba todas las demás transferencias de SPI.

Creo que esto se debe a esta línea:

while (!(SPSR & (1<<SPIF)))   ;

cuando realmente quieras:

while ((SPSR & (1<<SPIF)))   ;

Con suerte eso ahorra a alguien más parte del tiempo que pasé rascándome la cabeza.

    
respondido por el Mebert
1

También utilicé tu código fuente. Mi esclavo tiene solo 2 mensajes. La causa fue esta línea en la función SPI_SlaveReceive :

while (!(SPSR & (1<<SPIF)));

Esto solo es importante cuando usas SPI por sondeo. Si desea utilizar la comunicación SPI controlada por interrupciones - lado esclavo, elimine esta línea.

    
respondido por el Peter
0

Mejor tarde que nunca ¿verdad? Solo tuve el mismo problema, y ninguna de las respuestas anteriores es correcta, excepto la que tengo encima.

La función "uint8_t SPI_SlaveReceive (void)" está destinada a ser utilizada en main. para que sea activado por interrupciones, solo necesita leer el SPDR directamente en su isr.

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

    
respondido por el nuxil

Lea otras preguntas en las etiquetas