Forum: Mikrocontroller und Digitale Elektronik Erstes Byte über SPI immer falsch


von Christian B. (chris001)


Angehängte Dateien:

Lesenswert?

Hallo Leute!

Habe hier ein Testaufbau mit zwei µCs die über SPI verbunden sind.
An einem µC ist ein LCD für die Ausgabe angeschlossen.

Erklärung der beiden Programme:

Der Master sendet 3 Bytes zum Slave. Der Slave empfängt, und rechnen bei 
allen Bytes +1 und versendet dann wieder. Der Master empfängt die 3 
Bytes  und zeigt das Ergebnis im LCD an.

Das Problem was ich habe, das erste empfangene Byte entspricht immer 
genau dem letzten gesendeten Byte des Masters.

Außerdem verstehe ich nicht, wenn ich im Programm des Slaves den Wait 
Befehl ausklammer, Kommen nur nullen beim Master an.

Warum?

Danke für eure Beiträge....

LG....

von dummy (Gast)


Lesenswert?

>Das Problem was ich habe, das erste empfangene Byte entspricht immer
>genau dem letzten gesendeten Byte des Masters.

Das ist auch korrekt so. Du hast SPI nicht verstanden.

von nochwas (Gast)


Lesenswert?

Wie versendet der Slave ? Schau dir das mal an und lass uns dann 
teilhaben.

von Karl H. (kbuchegg)


Lesenswert?

Christian Betzen schrieb:
> Hallo Leute!
>
> Habe hier ein Testaufbau mit zwei µCs die über SPI verbunden sind.
> An einem µC ist ein LCD für die Ausgabe angeschlossen.
>
> Erklärung der beiden Programme:
>
> Der Master sendet 3 Bytes zum Slave. Der Slave empfängt, und rechnen bei
> allen Bytes +1 und versendet dann wieder.

Nö.
Der Slave versendet nicht.

Der Slave kann überhaupt nicht aktiv senden.
Es ist immer der Master, der die Kontrolle hat.

D.h. dein Master gibt 3 Bytes an den Slave.
Und dann will er 3 Bytes haben!
Dabei ist es ihm schei...egal, ob der Slave schon fertig ist oder nicht.
Mittels
Spiin Y(1) , 3
erzwingt er vom Slave das Herausrücken von 3 Bytes.


Genau genommen ist es bei SPI nicht so prickelnd von Senden und 
Empfangen zu sprechen. Eine SPI Übertragung ist ein Austausch von Bytes.
Während 1 Byte vom Master zum Slave geht, wird 1 Byte vom Slave zum 
Master übertragen.

Das ganze hat als mehr etwas von
Du sitzt am Tisch deinen Kumpel gegenüber. Jeder von euch beiden hat vor 
sich einen Zettel und einen Bleistift und kann eine Zahl (0-255) auf 
diesen zettel schreiben. Auf ein Signal von dir schiebt jeder mit seiner 
rechten Hand seinen Zettel zum Gegenüber, während er gleichzeitig mit 
der linken Hand den Zettel übernimmt, der ihm zugeschoben wird.

So funktioniert SPI eigentlich.
D.h. 'Senden' und 'Empfangen' sind eigentlich dasselbe, weil ein 
Austausch an Bytes erfolgt. Das man Senden und Empfangen trotzdem 
unterscheidet, liegt daran, weil man irgendwann ja auch mal festlegen 
will, was auf den Austauschzettel geschrieben werden soll, bzw. man 
daran interessiert ist, was auf dem Zettel stand, den man selbst 
gekriegt hat.

Aber der springende Punkt ist: Dein Kumpel hat keinbe Chance selbst 
aktiv zu werden. Du bist der Master und auf dein Signal hin werden die 
Zettel getauscht. Es spielt dabei keine Rolle ob dein Kumpel überhaupt 
schon was auf seinen Zettel geschrieben hat oder ob da noch das drauf 
stand, was du selber rübergeschoben hast. Wenn dein Kumpel kurz aufs Klo 
ging, dann ist es sehr wahrscheinlich, dass du dann genau wieder das 
zurück kriegst, was du selber zuletzt rüber geschoben hast.

: Bearbeitet durch User
von Christian B. (chris001)


Lesenswert?

Hi!

Ich habe noch nie was mit SPI gemacht. Sind die ersten Gehversuche.
Aber danke für den Hinweis, dass ichs nicht verstanden hab.

Ich glaube ich habe da schon ne Lösung gefunden.
Ich muss immer noch ein Dummybyte mitsenden. Damit das Register alle 
wichtigen Bytes in das Programm überträgt und nix wichtiges im Register 
stehen bleibt. Beim empfangen, kommt dann erst das Dummybyte, weil es 
noch im Register steht. Das verwerfe ich dann. Die danach empfangenen 
Bytes sind dann die, die ich haben will.

Wenn ich gleich wieder vorm PC bin probier ich das mal aus.
Kann mir jetzt noch einer sagen, warum ich ohne Wait nur nullen 
empfange?

Richtig?

von Bitflüsterer (Gast)


Lesenswert?

Der Vorgang hat noch eine weitere logische Ebene. Das hast Du mit dem 
"Dummy-Byte" eben mal so berührt, ohne es zu wissen.

Die Peripheriegeräte (das LCD etc.) reagieren nämlich aufgrund ihres 
gegenwärtigen Zustandes auf die vom Master gesendeten Daten mit dem 
zurücksenden von Daten die eben von diesem Zustand abhängen.
Das bezeichnet man als "Protokoll".

Die Beschreibung des Protokolls geht aus dem Datenblatt hervor.
Falls Du dazu weitere Fragen hast, poste uns bitte einen Link auf das 
Datenblatt.

von Christian B. (chris001)


Lesenswert?

Hi!

Dein Beispiel mit den Zetteln find ich toll. Hätte das nur mit 
Kartoffeln, Braten und Gemüse gemacht.

Wenn man so will, hat der Slave Gemüse für den Master in der Hand. Der 
Master gibt jetzt die Kartoffeln an den Slave und erhält dann das 
Gemüse.

Wenn der Slave jetzt den Braten haben will, muss er erst n Zettel 
schreiben wo Kartoffeln drauf steht und in die Hand holen. Aber erst 
wenn der Master dem Slave wieder das Gemüse zurück gibt, erhält der 
Master die Bestellung. Der Master kann jetzt gleich einen Austausch 
anstoßen und den Braten versenden und erhält dann wieder das Gemüse 
zurück.

Sry, ich bin beim Essen ;)

von Peter D. (peda)


Lesenswert?

SPI-Slave Senden ist beim AVR ein Albtraum, da ungepuffert.

Im Prinzip muß man folgendes machen:
- Master zieht /SS auf low und dreht Däumchen.
- Slave löst damit einen Interrupt aus und schreibt was in das 
SPI-Register
- wenn Master lange genug gewartet hat, schreibt er ein Dummybyte, um 
das Byte des Slave zu empfangen.
- Master liest das Byte und dreht wieder Däumchen.
- Slave kriegt Interrupt und schreibt das nächste Byte in das 
SPI-Register- - wenn Master lange genug gewartet hat, schreibt er ein 
Dummybyte, um das Byte des Slave zu empfangen.
- Master liest das Byte und dreht wieder Däumchen.
- Slave kriegt Interrupt und schreibt das nächste Byte in das 
SPI-Register
usw. usw.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Christian Betzen schrieb:
> Ich habe noch nie was mit SPI gemacht. Sind die ersten Gehversuche. Aber
> danke für den Hinweis, dass ichs nicht verstanden hab.
SPI sind einfach hintereinandergeschaltete Schieberegister:
http://www.lothar-miller.de/s9y/categories/17-SPI
Wenn man das mal kapiert hat, wird es auf einmal ganz einfach...

von Paul Baumann (Gast)


Lesenswert?

SPI macht Appetit und ist auf die Geselligkeit der Mitwirkenden dringend
angewiesen. Das konnte man hier sehr gut erklärt erfahren.

;-)
MfG Paul

von Christian B. (chris001)


Lesenswert?

Also gut!

In Bascom kann man aber jetzt leider keine Kartoffeln oder Gemüse 
austauschen, sondern nur Zahlen.

Auszug aus Beispielprogramm:

Master:

Spiout A(1) , 4                '4 Byte senden
Spiin Y(1) , 4                 '4 Byte empfangen

Slave:

Spiin A(1) , 4                 '4 Bytes empfangen
Spiout A(1) , 4                'die gleichen 4 Bytes wieder zurück 
senden

Das Ergebnis aus dem Programm ist, dass beim Master Y(1), a(4) 
entspricht.
Das liegt wohl daran, weil a(4) das letzte Byte noch im Register liegt, 
und dann beim empfangen wieder zurück in das erste Byte geschoben wird.
Wie mach ich das jetzt, dass er das erste Byte verwirft.


LG

von hmm (Gast)


Lesenswert?

Schluck.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Christian Betzen schrieb:
> Wie mach ich das jetzt, dass er das erste Byte verwirft.
Du ignorierst es einfach. So wie du im Bahnhof den Zug ignorierst, der 
vor deinem Zug am selben Gleis abfährt.

> Master:
> Spiout A(1) , 4                '4 Byte senden
> Spiin Y(1) , 4                 '4 Byte empfangen
>
> Slave:
> Spiin A(1) , 4                 '4 Bytes empfangen
> Spiout A(1) , 4                'die gleichen 4 Bytes wieder zurück
> senden
Ich weiß nicht, ob Bascom schon richtig reif für SPI ist. Denn ein Slave 
kann nicht erst 4 Bytes empfangen und dann von sich aus die 4 Bytes 
wieder zurücksenden. SPI empfängt und sendet immer gleichzeitig! 
(ich war versucht, hier mindestens 5 Ausrufezeichen zu machen!)
Das kannst du mit diesen Befehlen nicht abbilden...  :-/

: Bearbeitet durch Moderator
von Christian B. (chris001)


Lesenswert?

Alles klar, also sagen wir mal so...

Master:

Spiout A(1) , 4                '4 Byte senden
Spiin Y(1) , 4                 '4 Byte empfangen

y(1) = y(2)
y(2) = y(3)
y(3) = y(4)

Slave:

Spiin A(1) , 4                 '4 Bytes empfangen
Spiout A(1) , 4                'die gleichen 4 Bytes wieder zurück
senden

Damit werden dann die Empfangenen Bytes einfach in die andere Variable 
darunter verschoben. Funktioniert aber leider nicht :(

von Christian B. (chris001)


Lesenswert?

Hi!

> Ich weiß nicht, ob Bascom schon richtig reif für SPI ist. Denn ein Slave
> kann nicht erst 4 Bytes empfangen und dann von sich aus die 4 Bytes
> wieder zurücksenden. SPI empfängt und sendet immer gleichzeitig!
> (ich war versucht, hier mindestens 5 Ausrufezeichen zu machen!)
> Das kannst du mit diesen Befehlen nicht abbilden...  :-/

In der Bascom Hilfe wird der Befehl "spiin" und "spiout" aber so 
vorgeschlagen....

spiin x(1), 5 'Die fünf Bytes senden von x(1) bis x(5) usw... :-/

von Christian B. (chris001)


Angehängte Dateien:

Lesenswert?

Also gut!

Nachdem wohl alle ihr Pulver verschossen haben, im Anhang wie ich s 
gelöst habe. Es ist das Prinzip Ich beachte den Zug nicht der da gerade 
abfährt...

von MCUA (Gast)


Lesenswert?

>SPI-Slave Senden ist beim AVR ein Albtraum, da ungepuffert.
>Im Prinzip muß man folgendes machen:
>usw........
Ja stimmt (auch xmega hat das, wieso machen so en Schei?? etliche Jahre 
lang ohne es abzustellen??).
Allerdings, es geht doch continuierlich (also ohne 'dreht wieder 
Däumchen') wenn die SCLK so langsam gewählt wird (oder der Slave so 
schnell 'gemacht' wird) dass er zwischen 2 SCLKs genug Zeit hat das Byte 
zum SPI-TX zu schreiben. (oder man macht Handshake)


>SPI sind einfach hintereinandergeschaltete Schieberegister:
Ja, aber die Frage ist, wie s ein/ausgelesen wird.

von Karl H. (kbuchegg)


Lesenswert?

Christian Betzen schrieb:
> Hi!
>
>> Ich weiß nicht, ob Bascom schon richtig reif für SPI ist. Denn ein Slave
>> kann nicht erst 4 Bytes empfangen und dann von sich aus die 4 Bytes
>> wieder zurücksenden. SPI empfängt und sendet immer gleichzeitig!
>> (ich war versucht, hier mindestens 5 Ausrufezeichen zu machen!)
>> Das kannst du mit diesen Befehlen nicht abbilden...  :-/
>
> In der Bascom Hilfe wird der Befehl "spiin" und "spiout" aber so
> vorgeschlagen....


Das Problem ist eher, dass auch in BASCOM alle SPI nur als Master 
benutzen.

Beim Master gibt es an sich kein (allzugroßes) Problem.
Aber wenn SPI als Slave eingesetzt werden soll, dann macht das Ärger.

von Andreas G. (beastyk)


Lesenswert?

huhu,

das ist ein sehr leckerer Thread, der gefällt mir!

best wishes
dat
Beast

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Christian Betzen schrieb:
> In der Bascom Hilfe wird der Befehl "spiin" und "spiout" aber so
> vorgeschlagen....
Ich würde dieser Bibliothek erst trauen, wenn ich ihre Implementierung 
gesehen habe. Wenn tatsächlich solche Befehlssequenzen funktionieren
   Spiout A(1) , 4     '4 Byte senden
   Spiin Y(1) , 4      '4 Byte empfangen
dann muss irgeneine Art von Puffer eingebaut sein, oder die Funktion 
Spiin eine Beziehnung zu Spiout haben. Denn eines ist klar: wenn ich mit 
SPI 4 Bytes ausgebe, bekomme ich genauso 4 Bytes zurück.

von Peter D. (peda)


Lesenswert?

Christian Betzen schrieb:
> Nachdem wohl alle ihr Pulver verschossen haben, im Anhang wie ich s
> gelöst habe.

Du bekämpfst die Wirkung, aber nicht das Problem. Du wirst daher bald 
damit auf die Nase fallen.

Der Slave muß erstmal erkennen, wann ein neues Paket überhaupt anfängt. 
Also muß er mit der fallenden Flanke des /SS einen Interrupt auslösen 
und dann das 1. Byte ins SPDR schreiben.
D.h. /SS mit einem INT-Pin verbinden oder als Pin-Change Interrupt 
konfigurieren.

von Christian B. (chris001)


Lesenswert?

Der Slave Select SS wird doch über die Zeile SPI config aktiviert. In 
meiner Schaltung passiert auch nur was, wenn ich die Verbindung der 
beiden ss nutze.

Der Austausch von Bytes funktioniert jedenfalls. Es ergibt sich aber ein 
neues Problem. Wenn ich jetzt z.b. über nen 1W Bus nen Temperatursensor 
auslesen will, funktioniert die Übertragung der Bytes nicht mehr. Was 
muss ich da beachten?

Ich kann leider kein Programmschnipsel hier einbringen, bin z.Z. 
Unterwegs. Schreibt einfach mal was euch dazu einfällt.

von Peter D. (peda)


Lesenswert?

Christian Betzen schrieb:
> Wenn ich jetzt z.b. über nen 1W Bus nen Temperatursensor
> auslesen will, funktioniert die Übertragung der Bytes nicht mehr.

Was vollkommen logisch ist.
Dein Testprogramm benutzt ja 100% der CPU-Zeit für das SPI.

Sobald Du noch was anderes machen willst, mußt Du Interrupts benutzen.
Der externe Interrupt am /SS schreibt alle Bytes in einen Puffer und 
gibt dann den SPI-Interrupt frei.

von Interrupt (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Also muß er mit der fallenden Flanke des /SS einen Interrupt auslösen
> und dann das 1. Byte ins SPDR schreiben.
> D.h. /SS mit einem INT-Pin verbinden oder als Pin-Change Interrupt
> konfigurieren.

quark, ein spi interrupt loest automatisch aus, wenn ein byte empfangen 
ist

wenn der zettel beim slave angekommen ist, dann kriegt der automatisch 
mit, dass was da ist. der slave hat so lange zeit, das register zu lesen 
oder zu schreiben, bis der master das naechste byte gewechselt hat.
das spi register ist naemlich gelatcht
macht euch mal schlau, bevor ihr anfaengern irgendwelchen mist erzaehlt
spiin, spiout, spimove sind alles nur master befehle. wuerde ja auch 
keinen sinn beim slave machen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Interrupt schrieb:
> das spi register ist naemlich gelatcht
Das Empfangsregister schon.
Aber wenn du mit deinem AVR ein Slave bist und ein Byte versenden 
sollst, dann hast du das Problem, dass du vor dem ersten SCK-Impuls die 
zu versendenden Daten ins SPDR schreiben musst, denn das Senderegister 
ist nicht gepuffert.

> macht euch mal schlau, bevor ihr anfaengern irgendwelchen mist erzaehlt
Ja, so ist es. Du hast das Problem nicht korrekt erfasst.

: Bearbeitet durch Moderator
von Peter D. (peda)


Lesenswert?

Interrupt schrieb:
> quark, ein spi interrupt loest automatisch aus, wenn ein byte empfangen
> ist

Dann mußt Du aber beim Slave den Hellseherinterrupt aktivieren, damit er 
das erste zu sendende Byte in das SPDR schreibt, kurz bevor der Master 
SCK taktet.

Und wie soll der Slave wissen, ob es das erste Byte eines Pakets ist, 
wenn er keinen /SS-Interrupt auslöst?

von Walter Tarpan (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Interrupt schrieb:
>> quark, ein spi interrupt loest automatisch aus, wenn ein byte empfangen
>> ist
>
> Dann mußt Du aber beim Slave den Hellseherinterrupt aktivieren, damit er
> das erste zu sendende Byte in das SPDR schreibt, kurz bevor der Master
> SCK taktet.
>
> Und wie soll der Slave wissen, ob es das erste Byte eines Pakets ist,
> wenn er keinen /SS-Interrupt auslöst?

Oder man kopiert das zu schreibende Byte in den Puffer, sobald er 
ausgelesen wurden.

von Peter D. (peda)


Lesenswert?

Walter Tarpan schrieb:
> Oder man kopiert das zu schreibende Byte in den Puffer, sobald er
> ausgelesen wurden.

Je nach Abstand der Pakete kann dieses aber schon hoffnungslos veraltet 
sein.

SPI-Slave ohne MC werten immer die /SS-Flanke aus, um den Beginn eines 
Pakets festzustellen. In der Regel ist dann das erste Byte ein 
Kommandobyte, welches z.B. Daten senden bedeuten kann. D.h. ein Slave 
ohne MC sendet frühestens ab dem 2.Byte gültige Daten.

Ich habe SPI noch nie zur MC-MC Verbindung benutzt. Das ist mir einfach 
zu umständlich und vorallem zu unsicher.

: Bearbeitet durch User
von Walter Tarpan (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Je nach Abstand der Pakete kann dieses aber schon hoffnungslos veraltet
> sein.

Stimmt. Erst das zweite Byte kann aktueller sein.

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.