SPI no funciona, ATmega328 solo envía 1 byte

Estoy tratando de hacer que SPI funcione en un ATmega328. Este es mi código:

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define ACK 0x7E
#define LONG_TIME 10000

//Initialize SPI Master Device
void spi_init_master (void)
{
    DDRB = (1<<PORTB5)|(1<<PORTB3);              //Set MOSI, SCK as Output
    SPCR = (1<<SPE)|(1<<MSTR); //Enable SPI, Set as Master

}

//Function to send and receive data
unsigned char spi_tranceiver (unsigned char data)
{
    PORTC = 1<<PORTC2;
    PORTC = 0<<PORTC2;

    SPDR = data;                       //Load data into the buffer
    while(!(SPSR)&(1<<SPIF));
    return(SPDR);                      //Return received data
}


//Main
int main(void)
{
    DDRC= 0XFF; 
    spi_init_master();
    spi_tranceiver(6); 
    //spi_tranceiver(6);
    //spi_tranceiver(6); 


}

Esta es la salida del analizador lógico:

ingrese la descripción de la imagen aquí

Observe esas dos líneas de comentarios. spi_tranceiver(6);Si elimino esos comentarios, debería obtener, del analizador lógico:

  • 3 veces la cantidad de pulsos de reloj para la capa azul.
  • 3 veces la cantidad de datos enviados, y;
  • 3 veces la cantidad de pulsos PORTC2.

Este no es el caso. Obtengo lo siguiente:

ingrese la descripción de la imagen aquí

El dispositivo con el que intento SPI no está configurado correctamente. ¿Importa esto?

Respuestas (1)

Parece que tiene los paréntesis en el lugar equivocado mientras espera que se complete la transacción SPI. Debido a que el !operador tiene una precedencia más alta, &intentará hacer un bit a bit del SPSRregistro primero. En cambio, quieres algo como esto:

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

En este momento, presumiblemente, la espera regresa de inmediato, por lo que el SPDRregistro se configura tres veces en rápida sucesión sin tiempo suficiente para que se transfieran los datos.

¡muchas gracias! ¡He pasado muchas, muchas horas en esto!
Además, suponiendo que PORTC2 es la línea SS/CS, debe mantenerse bajo durante la totalidad de su 'transacción' SPI, y debe sacarse de su spi_tranceiverfunción y moverse a algún lugar alrededor de eso.