Hallo zusammen,
ich beschäftige mich gerade mit einer SPI Realisierung in Software. Es
soll eine Verbindung zwischen einem Atmega 644P und einem ARM6
hergestellt werden.
Hardware SPI ist auf beiden Seiten belegt, deswegen werden drei normale
IO Pins verwendet.
Mein Master im Atmega 644P gibt per Pin Toggle mit 9,7kHz den Takt vor.
Meine Vorstellung der Funktionsweise:
Ich gebe den Takt auf einem Pin aus, die somit als Clock Leitung
fungiert.
Der Slave erkennt nun eine steigende Flanke auf der Clock Leitung und
übernimmt die Daten an seinem InputPin. Wie weiß der Master wann er mit
dem Senden beginnen darf? Direkt nachdem er sein Clock Signal auf die
Leitung gegeben hat?
Der Slave empfängt nun die Daten an seinem InputPin bei steigender
Flanke der Clock Leitung und setzt ein Bit auf seine Output Leitung,
wenn eine fallende Flanke detektiert wurde.
Beendet wird das ganze sobald kein Clock Signal mehr anliegt.
Beide Seiten senden also immer Vollduplex wenn ein Clock Signal anliegt?
Danke!
Grüße,
Sepp
Sepp schrieb:> Wie weiß der Master wann er mit> dem Senden beginnen darf? Direkt nachdem er sein Clock Signal auf die> Leitung gegeben hat?
Nein.
Der Master setzt das Slave-Select auf low und damit weiß der Slave, daß
er nun adressiert ist.
Dann werden beliebig viele Bytes übertragen und danach setzt der Master
das Slave-Select wieder auf high. Damit weiß der Slave, daß er sich
wieder vom Bus verabschieden und die empfangenen Daten auswerten darf.
SPI braucht also mindestens 4 Leitungen und für jeden weiteren Slave
noch eine.
Getaktet wird nur sobald ein Slave-Select auf low ist.
Peter
Peter Dannegger schrieb:> Nein.> Der Master setzt das Slave-Select auf low und damit weiß der Slave, daß> er nun adressiert ist.> Dann werden beliebig viele Bytes übertragen und danach setzt der Master> das Slave-Select wieder auf high. Damit weiß der Slave, daß er sich> wieder vom Bus verabschieden und die empfangenen Daten auswerten darf.>> SPI braucht also mindestens 4 Leitungen und für jeden weiteren Slave> noch eine.> Getaktet wird nur sobald ein Slave-Select auf low ist.
Bei einem Hardware SPI gebe ich Dir Recht, aber meine Variante sollte
auf beiden Seiten in Software realisiert sein. Brauche ich trotzdem 4
Leitungen?
Bisher dachte ich drei würden genügen, es existiert in meiner Variante
ja lediglich ein Slave (Punkt zu Punkt).
Sepp schrieb:> Bei einem Hardware SPI gebe ich Dir Recht, aber meine Variante sollte> auf beiden Seiten in Software realisiert sein. Brauche ich trotzdem 4> Leitungen?> Bisher dachte ich drei würden genügen, es existiert in meiner Variante> ja lediglich ein Slave (Punkt zu Punkt).
Es steht dir natürlich frei, dein eigenes Schema zu erfinden und das
dann SPI zu nennen. Solange es funktioniert ist dagegen auch nichts
einzuwenden. Nur wird sich dein Nachfolger dann etwas wundern, wenn du
ihm ein SPI verkaufst, welches gar kein SPI ist sondern nur so ähnlich.
Zumindest nicht das, was gemeinhin unter SPI verstanden wird.
Karl heinz Buchegger schrieb:> Es steht dir natürlich frei, dein eigenes Schema zu erfinden und das> dann SPI zu nennen. Solange es funktioniert ist dagegen auch nichts> einzuwenden. Nur wird sich dein Nachfolger dann etwas wundern, wenn du> ihm ein SPI verkaufst, welches gar kein SPI ist. Zumindest nicht das,> was gemeinhin unter SPI verstanden wird.
Ich wollte schon standardkonform sein, mir stehen aber nur 3 Pins zur
Verfügung. Evtl. wäre ein vierter rauszukitzeln, das müsste aber noch
geklärt werden.
Per Slave Select schicke ich dann ein Low Signal um meinem Slave
mitzuteilen, dass er nun auf seine Input Leitung horchen muss. In dem
Moment wo die SS Leitung auf High geht ist meine Übertragung beendet?
Die Clock Leitung wird dannn mit der SS aktiviert oder deaktiviert?
Sepp schrieb:> Die Clock Leitung wird dannn mit der SS aktiviert oder deaktiviert?
Mir scheint, du hast da irgendwie falsche Vorstellungen davon, was die
Clock Leitung eigentlich macht.
Die Clock Leitung ist nicht einfach nur 1 Takt auf dem eine Schwingung
rausgeht.
So ist das Synchronisierungsinstrument. Eine Flanke auf der Clock
Leitung sagt dem Gegenüber: Hey Alder, die Datenleitung hab ich richtig
eingestellt, genau jetzt holst du dir den Pegel davon bitte ab.
D.h. der Master setzt seine Datenleitung auf 0 oder 1, was er eben
braucht und erst dann wechselt er die Clockleitung um seinem Gegenüber
anzuzeigen, dass der Zustand auf der Datenleitung gültig ist.
Man kann auch 3 Leitungen nehmen, wenn der Datenpin bidirektional ist.
Kann man z.B. bei vielen SPI-EEPROMs so machen (DI + DO verbinden).
Nach dem Select = low ist der Datenpin beim Slave erstmal Eingang und
liest ein Kommando ein.
Ist es ein Lesekommando, schaltet er danach um auf Ausgang und sendet
dem Master die zu lesenden Daten.
Peter
Karl heinz Buchegger schrieb:> Mir scheint, du hast da irgendwie falsche Vorstellungen davon, was die> Clock Leitung eigentlich macht.>> Die Clock Leitung ist nicht einfach nur 1 Takt auf dem eine Schwingung> rausgeht.> So ist das Synchronisierungsinstrument. Eine Flanke auf der Clock> Leitung sagt dem Gegenüber: Hey Alder, die Datenleitung hab ich richtig> eingestellt, genau jetzt holst du dir den Pegel davon bitte ab.>> D.h. der Master setzt seine Datenleitung auf 0 oder 1, was er eben> braucht und erst dann wechselt er die Clockleitung um seinem Gegenüber> anzuzeigen, dass der Zustand auf der Datenleitung gültig ist.
Klasse Antwort, jetzt kommt immer mehr Licht ins Dunkel (-:
Der Slave weiß nun durch eine Flanke, dass er das Bit auf seiner Input
Leitung abholen soll.
Wie sieht die Sache nun aus wenn der Slave sendet? Legt er einfach sein
Bit auf die MISO, Problem hierbei wäre doch, dass der Master mitbekommen
muss wann er etwas auf der Input Leitung abholen soll?
Sepp schrieb:> Der Slave weiß nun durch eine Flanke, dass er das Bit auf seiner Input> Leitung abholen soll.> Wie sieht die Sache nun aus wenn der Slave sendet?
Dann muss er rechtzeitig seine Datenleitung auf den richtigen Pegel
setzen. Er muss damit fertig sein, ehe der Master die Clock Leitung
toggelt.
Der Master gibt also nicht nur den Takt vor, in dem er selber Daten zum
Slave schickt, sondern er gibt auch dem Slave vor, wann er auf der
Rückleitung einen korrekten Pegel erwartet.
Da gibt es jetzt natürlich mehrere Möglichkeiten, wie das konkret
gemacht werden kann. zb eine steigende Flanke steuert den Transfer vom
Master zum Slave, dann hat der SLave Zeit sein Bit auf die Leitung zu
lesen und mit der fallenden Flanke holt sich dann der Master dieses Bit.
ABer wie gesagt: Da gibt es mehree Varianten. Daher gibt es ja auch SPI
in verschiedenen Modi
http://de.wikipedia.org/wiki/Serial_Peripheral_Interface#Protokollablauf_und_Einstellm.C3.B6glichkeiten
Karl heinz Buchegger schrieb:> Da gibt es mehree Varianten. Daher gibt es ja auch SPI> in verschiedenen Modi
Ok wunderbare Erklärung! Ich möchte gerne den Modus 0 mit CPOL und CPHA
0 verwenden. Darunter versteht man doch, dass die Daten bei der ersten
Flanke, also bei der steigenden übernommen werden.
Hier mein angedachter Ablauf:
- Master legt Bit auf MOSI und toggelt die Clock von Low auf High
- Slave Select wird Low
- Slave erkennt pos. Flanke an Clock und übernimmt an MOSI
- Slave legt sein Datenbit auf MISO
- Master übernimmt die Daten auf MISO wenn er Clock von High auf Low
schaltet
- Nun legt wieder der Master sein Bit auf MOSI und toggelt die Clock auf
High
- Schleife beginnt...
Verständnisprobleme bereitet mir aber die Synchronisation beim Slave,
angenommen mir stehen keine Pin Change Interrupts zur Verfügung, dann
muss der Slave in einer Schleife den Wert des Clock Pins abfragen. Hier
ist es doch erforderlich die Durchlaufzeit ähnlich der Schleife beim
Master zu haben? Angenommen der Master ist viel schneller, dann wird der
Slave doch niemals einen Clock Wechsel mitbekommen...
Anders gefragt, bei unterschiedlich ausgelasteten Mikrocontrollern auf
beiden Seiten ist doch ein Interrupt zwingend erforderlich?
Sepp schrieb:> Angenommen der Master ist viel schneller, dann wird der> Slave doch niemals einen Clock Wechsel mitbekommen...
Du hast es erfaßt.
Slave-SPI ist extrem ressourcenhungrig und macht man daher in der Regel
nicht in Software.
Slave-SPI benötigt 2 externe Interrupts mit der höchsten Priorität (darf
alle anderen Interrupts unterbrechen). Slave-SPI auf CPUs ohne
Prioritätslevel kannste voll vergessen.
Und der AVR ist trotz HW-SPI als Slave-SPI völlig unbrauchbar, da er
keinen Sendepuffer hat. Er hat praktisch genau 0ns Zeit, ein Byte in das
Senderegister zu schreiben.
Eine SPI-Verbindung zwischen 2 MCs ist daher so ziemlich das schlimmste,
was man sich als Programmierer antun kann.
Man nimmt besser I2C, UART oder CAN.
Peter
Peter Dannegger schrieb:> Slave-SPI benötigt 2 externe Interrupts mit der höchsten Priorität (darf> alle anderen Interrupts unterbrechen). Slave-SPI auf CPUs ohne> Prioritätslevel kannste voll vergessen.
Reicht nicht ein Pin Change Interrupt am Clock Pin? Dort könnte ich doch
dann jeden Wechsel erkennen und Daten übernehmen und rausschreiben.
Ich benötige eine Verbindung von einem Atmel644P zu einem ARM7 TDMI.
Auf dem Atmel sind gerade noch 3 IO Pins verfügbar, kein HW UART oder HW
SPI, alles bereits belegt. Deswegen die fiel die Wahl auf Software SPI.
Dummerweise sind auf dem ARM7 auch noch die Pins für externe
Interrupts(Pin Change) vergeben. Naja und das stellt mich vor die großen
Probleme wie oben beschrieben.
Mittlerweile bin ich soweit ein Arduino Uno Platine dazwischen zu
schalten.
So solls dann aussehen:
Atmega644P(Master SW SPI) <---> Arduino Uno(Slave SW SPI PinChange
Interrupts)||| ArduinoUno(HW UART) <---> ARM7(HW UART)
Meinungen dazu?
Sepp schrieb:> Mittlerweile bin ich soweit ein Arduino Uno Platine dazwischen zu> schalten.> So solls dann aussehen:
Du hast ja auch noch die Möglichkeit, die Probleme im SPI wenigstens ein
bischen zu entschärfen, indem du das SPI ein wenig abwandelst.
Grundzustand ist
MOSI Low
MISO High
SCLK High
Der Master möchte etwas übertragen.
Er beginnt damit, den Slave zu benachrichtigen, indem er SCLK auf Low
zieht. Und dann wartet er.
Der Slave pollt regelmässig seinen SCLK Eingang. Solange der High ist,
gibt es keine Anfrage.
Ist SCLK auf Low, dann ist vom Master die Aufforderung gekommen: Ich
will was übertragen.
Als Antwort darauf zieht der Slave die MISO Leitung von High auf Low und
stellt alle anderen Arbeiten sowiet wie möglich ein um möglichst viel
Prozessorzeit auf das überwachen der SCLK Leitung frei zu haben.
Das wiederrum kriegt der Master mit, der nur darauf gewartet hat. Das
Low auf MISO zeigt ihm, dass der Slave nun zuhört.
Also setzt er MOSI anhand des zu übertragenden Bits, wartet vielleicht
noch ein wenig und zieht SCLK wieder auf High und wartet wieder ein
wenig.
Dieses High ist für den Slave wiederrum die Aufforderung sich das Bit
vom MOSI zu holen. Gleichzeitig ist es auch die Freigabe das erste Bit
seines eigenen Bytes auf MISO zu legen.
Hat der Master seine Bitwartezeit absolviert dann zieht er SCLK wieder
auf Low und holt sich das Bit vom MISO
Und so gehts immer weiter.
Problematisch sind natürlich immer noch die Wartezeiten, die der Master
einlegen muss um mittels SCLK die Übertragung zu takten.
Aber zumindest für den Verbindungsaufbau hat der Master die Gewissheit,
dass er den Slave nicht soweit überfährt, dass der noch gar nicht bereit
ist, ehe er loslegt.
Karl heinz Buchegger schrieb:> rundzustand ist>> MOSI Low> MISO High> SCLK High>> Der Master möchte etwas übertragen.> Er beginnt damit, den Slave zu benachrichtigen, indem er SCLK auf Low> zieht. Und dann wartet er.>> Der Slave pollt regelmässig seinen SCLK Eingang. Solange der High ist,> gibt es keine Anfrage.> Ist SCLK auf Low, dann ist vom Master die Aufforderung gekommen: Ich> will was übertragen.> Als Antwort darauf zieht der Slave die MISO Leitung von High auf Low und> stellt alle anderen Arbeiten sowiet wie möglich ein um möglichst viel> Prozessorzeit auf das überwachen der SCLK Leitung frei zu haben.>> Das wiederrum kriegt der Master mit, der nur darauf gewartet hat. Das> Low auf MISO zeigt ihm, dass der Slave nun zuhört.
Das Konzept werde ich mal übernehmen.
Nun hat sich doch etwas zum Guten geändert in meiner Ausgangssituation:
Der ARM muss pro Sekunde 4 Rechenzyklen durchlaufen von denen ein Zyklus
ca. 130ms braucht. D.h. ich habe danach 120ms pro Zyklus für meine SPI
Übertragung.
In dieser Zeit kann ich den ARM alleine als Software SPI Master nutzen.
Der Atmel würde nun zum Software SPI Slave degradiert und kann auf der
Clock Leitung nun auf Pin Change Interrupts reagieren.
So sollte die Übertragung gelingen....