Forum: Mikrocontroller und Digitale Elektronik Fragen zu SPI mit AVR


von David P. (devryd)


Lesenswert?

Hallo zusammen,
ich versuche gerade SPI auf meinem Atmega1284p zum laufen zu bekommen. 
Ich habe das Datenblatt gelesen, allerdings hilft es mir nicht wirklich 
weiter.
Im Datenblatt wird erklärt, wie man ein Byte schickt, aber wie genau ist 
das Vorgehen, wenn ich mehr als ein Byte schicken will, zum Beispiel ein 
Byte Adresse und ein Byte Daten. Setze ich zwischen die einzelnen 
"Übertragungen" ein Delay?
Wenn ja, wie lang?
Im Datenblatt steht habe ich leider nur diesen Beispielcode gefunden:
1
void SPI_MasterTransmit(char cData){
2
/* Start transmission */
3
SPDR = cData;
4
/* Wait for transmission complete */
5
while(!(SPSR & (1<<SPIF)));
6
}
Dazu muss ja noch Slave select auf low gelegt werden.
Hat jemand ein Stück Beispielcode für mich?
Gruß David

von Veit D. (devil-elec)


Lesenswert?

Hallo,

dein gezeigter Code macht das schon.

SPDR ist das SPI Datenregister für Bytes.

Und die Zeile sorgt dafür das es erst weiter geht wenn das SPDR wieder 
leer ist, also gesendet wurde und bereit ist für die Aufnahme des 
nächsten Bytes. Einen Buffer gibts nicht.
1
while(!(SPSR & (1<<SPIF)));

und vorher konfigurierst du das SPI Modul noch wie benötigt, Bsp.
1
//     enable SPI,   LSB first,      Master,       fck/4
2
SPCR = (1 << SPE) | (1 << DORD) | (1 << MSTR);
3
SPDR = 0;   
4
sei();

Und vorm Datentransfer Chip Select auf Low und wenn alle Daten gesendet 
sind und SPDR leer wieder auf High.

: Bearbeitet durch User
von David P. (devryd)


Lesenswert?

Ich glaube ich habe meinen Fehler gefunden:
ich habe CS high gezogen, daten geschickt und dann cs low gezogen
also genau falsch rum.
Mal sehen ob es jetzt klappt.

von David P. (devryd)


Lesenswert?

Leider funktioniert es immer noch nicht.
Zur Initialisierung mache ich das:
1
DDRB |=  (1<<PB1)| (1<<PB5)| (1<<PB7);
2
PORTB |= (1<<PB1); //pull CS high
3
SPCR = 0b01010000;
4
_delay_ms(100);

Weiter unten im Code folgt:
1
while(1){
2
    
3
    
4
    PORTB &=~(1<<PB1);
5
    _delay_us(100); //wait vor cs to be low
6
    PORTD=0;    //turn off leds for diagnostic purposes
7
    _delay_ms(100);
8
    SPDR=0x81; //send register
9
    while (!(SPSR &(1<<SPIF)));    
10
    SPDR=0x00;    //send data
11
    while (!(SPSR &(1<<SPIF)));
12
    PORTD=0xFF; //turn on leds for diagnostic purposes
13
    PORTB|= 1<<PB1;
14
    
15
    _delay_ms(1000);
16
    
17
  }

Der Atmega kommt gar nicht erst bei der Zeile : PORTD=0xFF; an.

von Falk B. (falk)


Lesenswert?

David P. schrieb:
> Leider funktioniert es immer noch nicht.
> Zur Initialisierung mache ich das:DDRB |=  (1<<PB1)| (1<<PB5)| (1<<PB7);
> PORTB |= (1<<PB1); //pull CS high
> SPCR = 0b01010000;
> _delay_ms(100);

Man MUSS das SS-Pin (PB4) als Ausgang konfigurieren, siehe "SS pin 
functionality" im Datenblatt.

von David P. (devryd)


Lesenswert?

Und wie spreche ich dann 2 verschiedene slaves an?

von Wolfgang (Gast)


Lesenswert?

David P. schrieb:
> Und wie spreche ich dann 2 verschiedene slaves an?

Nacheinander oder gleichzeitig.
Wenn du die Slaves nacheinander ansprechen willst, braucht jeder sein 
eigenes CS-Signal. Wenn du die Slaves in Serie schaltest (Daisy-Chain), 
brauchst du nur eins, aber die Slaves müssen die Daten immer 
durchreichen.

von S. Landolt (Gast)


Lesenswert?

Es heißt ja nur, dass B4 ein Ausgang sein muss, damit der SPI-Master 
nicht (versehentlich) in den Slave-Modus geschaltet wird. B4 braucht 
nicht notwendigerweise eine CS-Funktionalität zu haben, auch wenn dies 
im Regelfall sinnvoll ist.

von Heiner (Gast)


Lesenswert?

Wolfgang schrieb:
> David P. schrieb:
>> Und wie spreche ich dann 2 verschiedene slaves an?
>
> Nacheinander oder gleichzeitig.
> Wenn du die Slaves nacheinander ansprechen willst, braucht jeder sein
> eigenes CS-Signal. Wenn du die Slaves in Serie schaltest (Daisy-Chain),
> brauchst du nur eins, aber die Slaves müssen die Daten immer
> durchreichen.

Es ist aber sinnvoller, es mit 2 CS-Signalen zu machen (keine 
Daisy-Chain), da Du dann unabhängiger bist; und es müsste doch noch ein 
Ausgang als 2.tes CS Signal zur Verfügung stehen

NB - was willst Du per SPI ansteuern?

von Wolfgang (Gast)


Lesenswert?

Heiner schrieb:
> Es ist aber sinnvoller, es mit 2 CS-Signalen zu machen (keine
> Daisy-Chain), da Du dann unabhängiger bist;

Das kommt sehr auf den Anwendungsfall an.
Wenn es z.B. darum geht, ein paar mehr LEDs per 74hc595 anzusteuern, ist 
Daisy-Chain ausgesprochen sinnvoll. Genauso sieht es aus, wenn du 
irgendwelche Eingänge über PISO-Schieberegister einlesen willst. 
Unabhängigkeit macht die Sache in so einem Fall nur komplizierter.

von David P. (devryd)


Lesenswert?

Ich möchte mit einem sx1276 lora Modul kommunizieren.
Wenn ich zuhause bin, probiere ich es nochmal den pin als output zu 
nutzen.

von Wolfgang (Gast)


Lesenswert?

David P. schrieb:
> Ich möchte mit einem sx1276 lora Modul kommunizieren.

Die Pegel deines SPI passen dazu?

von David P. (devryd)


Lesenswert?

Jap, beides 3.3V

von Heiner (Gast)


Lesenswert?

Soll der Datenaustausch per SPI gepollt werden oder per SPI Interrupt?

Soll der Master auch Daten vom Slave auswerten (er empfängt ja Daten vom 
Slave)?

Wieviele Daten sollen ausgetauscht werden?

von David P. (devryd)


Lesenswert?

Es werden 2 Byte Daten über lora gesendet + ein paar Byte zum 
konfigurieren des lora Moduls. Der Master muss keine Daten auswerfen, 
aber zum Fehler finden wäre evtl hilfreich.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.