SPI funktioniert nicht, ATmega328 sendet nur 1 Byte

Ich versuche, SPI auf einem ATmega328 zum Laufen zu bringen. Das ist mein Code:

#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); 


}

Dies ist die Ausgabe des Logikanalysators:

Geben Sie hier die Bildbeschreibung ein

Beachten Sie diese beiden Kommentarzeilen. spi_tranceiver(6);Wenn ich diese Kommentare entferne, sollte ich vom Logikanalysator Folgendes erhalten:

  • 3-fache Anzahl von Taktimpulsen für die blaue Schicht.
  • 3-fache Menge der gesendeten Daten und;
  • 3 mal die Menge an PORTC2-Impulsen.

Das ist nicht der Fall. Ich bekomme folgendes:

Geben Sie hier die Bildbeschreibung ein

Das Gerät, mit dem ich SPI versuche, ist nicht richtig konfiguriert. Spielt das eine Rolle?

Antworten (1)

Es sieht so aus, als hätten Sie die Klammern an der falschen Stelle, während Sie auf den Abschluss der SPI-Transaktion warten. Da der !Operator eine höhere Priorität hat, &wird SPSRzuerst versucht, das Register bitweise nicht zu verwenden. Stattdessen möchten Sie so etwas:

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

Im Moment kehrt dieses Warten vermutlich sofort zurück, sodass das SPDRRegister dreimal schnell hintereinander gesetzt wird, ohne dass genügend Zeit für die Übertragung der Daten vorhanden ist.

vielen Dank! Ich habe viele, viele Stunden damit verbracht!
spi_tranceiverUnter der Annahme, dass PORTC2 die SS/CS-Leitung ist, sollte diese während der gesamten SPI-'Transaktion' niedrig gehalten und aus Ihrer Funktion herausgenommen und an einen Ort in der Nähe verschoben werden.