Forum: Mikrocontroller und Digitale Elektronik SPI: Bidirektionale Datenübertragung


von Thomas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe mir in den vergangenen Tagen schonmal Hilfe im GCC-Forum
geholt. Leider konnte mir eine Frage nicht beantwortet werden, sodass
ich mich mit dem Problem nochmal an Euch wende.

In der angefügten Datei habe ich den Quelltext für Sklave- und
Mastercontroller angehängt. Folgende Sache klappt bisher:


- Master löst via Timer-ISR eine SPI-DÜ mit Inhalt 0xAA raus
  + Timer-Reload
  + /SS=0
  + SPDR mit 0xAA laden
- Master SPI complete ISR
  + /SS=1

- Sklave nur Datenempfang (DDRB=0x00)
- Sklave SPI complete ISR
  + Ausgabe des Datenframe von Master (PORTC = SPDR)

Jetzt wollte ich gerne einen Datenframe von Sklave an den Master
zurückschicken und habe folgende Änderungen/Zusätze (wie im Anhang)
gemacht:

- Sklave:
  + in der SPI complete ISR vorm Auslesen den zu sendenden Frame
setzten:
    <c>
    //SPI transfer complete
    ISR(SPI_STC_vect)
    {
      SPDR = 0x04;  //return 0x04 to master
      PORTC = SPDR;  //reading SPI-data
    }
    </c>
- Master:
  + in der SPI complete ISR Sklave auslesen

    <c>
    //SPI transfer complete
    ISR(SPI_STC_vect)
    {
      PORTB |= 0x01; // /SS=1
      PORTD = SPDR;  //data from sklave at PORTC
    }
    </c>

Weiterhin habe ich die Portrichtung des PORTB des Sklave auf DDRB=0x40
(MISO Output)  gesetzt. Durch diese Änderung klappt die DÜ
Master->Sklave nicht mehr.

Hat jemand eine Idee?

Mfg
Thomas

von Dirk (Gast)


Lesenswert?

Hi,

ich wuerde es alles ein kleines bischen anders loesen.


1. Master: sendet Commando.
2. Slave: Wartet auf SPI Interupt (1 Byte komplett), setzte ein
status_flag fuer komplett.
3. Slave: Main Routine fragt dieses Flag ab, wenn das Flag gesetzt
werte das Commandobyte vom Master aus und legt den Rueckgabewert in
SPDR.
4. Master sendet 1 Byte und prüft danach das SPDR auf den
Rueckgabewert.

Hoffe es reicht soweit aus, ansonsten habe ich zu Hause noch ein
kleines Master Slave Beispiel.

Muss der Slave bei Dir unbedingt die Masterrolle uebernehmen?

Gruß,
Dirk

von Thomas (Gast)


Lesenswert?

Der Sklave soll eigentlich keine Masterroller übernehmen. In meinem
Beispiel arbeitet der ATMEGA128 alleinig als Master, der zyklisch eine
Nachricht an den Sklave schickt. Gleichzeitig soll der Sklave einfach
nur 1 Byte zurückschicken und eben das klappt nicht.

Sobald ich die Portrichtung der MISO-Leitung des ATMEGA32 auf Ausgang
setze, geht nix mehr.

Viele Grüße
Thomas

von Dirk (Gast)


Lesenswert?

Hi,

der SPI Bus ist ein Schieberegister mehr nicht. Du musst schon vom
Master ein Byte senden zum Slave damit der Master was im SPDR Register
vom Slave erhaelt. Bei bedarf poste ich nen kleines Beispiel.

Gruß,

Dirk

von Thomas (Gast)


Lesenswert?

Genau das mache ich doch, oder?

(1) Im "Leerlauf" lädt Master als auch Sklave ein Byte in den SPDR
(2) Master schickt ein Byte an Sklave
(3) beim kompletten Empfang auf Sklave-Seite wird dort eine ISR
aufgerufen und das "Masterbyte" ausgelesen

Bisher geht die Datenübertragung vom Master zum Sklave (wenn MISO-Pin
beim Sklave auf 0x00) aber nicht vom Sklave zum Master. Dabei ist mir
folgendes Problem aufgefallen. Sobald ich die Portrichtung (PORTB) am
Sklave so setze, dass das MISO-Pin als Ausgang (DDRB=0x40) geht auch
die DÜ zum Sklave nicht mehr. Kann es sein, dass die Verdrahtung
MISO/MOSI "kreuzweise"  gemacht werden muss.

Beispiel würde mich auch freuen. Obwohl ich im ersten Posting ja schon
einen Quelltext verlinkt habe.

Mfg
Thomas

von Frankl (Gast)


Lesenswert?

SPI geht nur vom Master zum Slave. MOSI auf MOSI, MISO auf MISO, SCK auf
SCK. Willst du was zum Master senden muß der Master dem Slave ein Byte
schicken. Willst du davon unabhängig sein, mußt Du ein Multimaster
programmieren. Oder du missbrauchst den SS Eingang als Sendeanforderung
zum Master wobei dann vom Slave die Daten zum Master übertragen werden.

von Thomas (Gast)


Lesenswert?

Erstmal vielen Dank für die Antworten. Mir ist das Prinzip schon klar.
Ich habe aber genau hier das Problem der praktischen Umsetzung.

Ich habe ja extra meinen Quellcode im 1.Posting angehängt, damit ich
eine Lösung für mein Problem erhalte. Dort ist der Master ein ATMEGA128
und der soll es auch bleiben. Er schickt aller einer Sekunden ein Byte
an den Sklave und dieses zeigt der Sklave schön brav an PORTC an.

Als Ergänzung wollte ich jetzt gerne, dass der Sklave bei jeder
Master-Übertragung ein beliebiges Byte (z.B. 0xAA) auf der MISO-Leitung
legt. Hierfür muss ich aber das SPI-Port (PORTB) so initialisieren, dass
die MISO-Leitung (PB6) als Ausgang geschalten ist. Sobald ich diese
Änderung auf dem Sklavecontroller compiliere und in den Flash
speichere, geht die Datenübertragung garnicht mehr. (Master-Byte wird
auf Sklave nicht mehr an PORTC ausgegeben).

Gibts dafür eine Erklärung?

Mfg Thomas

von Josef (Gast)


Lesenswert?

Hallo

ich habe das selbe Problem. Ich kann auf der Seite des Slave ein Byte
ins SPDR schreiben, aber die Daten werden nicht bei der nächsten
Übertragung gesendet, sondern lediglich das alte Byte das vorher
Empfangen wurde.

Verwendeter Controller ATMega64. Also das selbe Problem.

Scheinbar hat der Controller einen Bug, oder das Datenblatt ist
fehlerhaft. Laut Datenblatt soll man den zu senden Wert in das SPDR
Register schreiben bevor man das empfangene Byte ausliesst. Aber egal
in welcher Reihenfolge ich das mache, es tut nicht. Der Empfang vom
Master klapt dagegen problemlos.

von Josef (Gast)


Lesenswert?

Noch mal zur Ergänzung. Das Ganze verhält sich so, als ob der
Schreibzugriff auf das SPDR keine Wirkung hat. Die alten Daten bleiben
erhalten und werden auch wieder raus geshiftet.

Also MISO  MOSI  CLK funktionieren. Das ganze betrifft scheinbar nur
den Schreibzugriff auf das SPDR im Slave Modus.

Kennt jemand das Problem?

von Josef (Gast)


Lesenswert?

Hallo noch eine weitere Eingrenzung der Frage.

Kann es sein, dass wenn /SS auf low liegt und der Slavemode aktiv ist
(MSTR = 0), nicht auf das SPDR geschrieben werden kann? Blöderweise
liegt bei mir /SS hart auf GND. So kann ich das nicht mal auf die
Schnelle testen.

Das Datenblatt lässt dieses Frage leider offen.

von Josef (Gast)


Lesenswert?

So bei mir war der Grund, dass das letzte Byte noch nicht komplett
eingeschoben war, bzw es gab eine Überschneidung beim letzten
empfangenen Bit und dem zu senden Bit.

Die Lösung ist, das SPI Interface abzuschalten. Die Daten aus dem SPDR
zu retten, die zu sendenen Daten reinschreiben und das Interface wieder
einschalten. Das ist zwar eine Vergewaltigung der Schnittstelle aber es
funktioniert.

So long.

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.