Hallo zusammen, Ich möchte eine DaisyChain von SPI Slave-Geräten zur bidirektionalen Kommunikation verwenden. DaisyChain heißt, alle SlaveSelects (SS) der Slaves sind zusammengeschalten (der Master hat ohnehin nicht genügend Pins). Erschwerend kommt hinzu, dass die Slaves nicht wissen, wie viele Geräte in der Kette hängen. bidirektional habe ich mir so vorgestellt: Sagen wir, wir haben 8 Slaves. Jeder soll ein bestimmtes Byte an Daten erhalten (also sind vom Master 8 Bytes zu senden). Hat jeder sein Byte erhalten, schreiben die Slaves ihrerseits je ein Byte Rückgabewert in ihre Register und senden den Datenstrom zurück an den Master. Er bekommt also 8 Bytes Rückgabewerte. Bei Schieberegistern ist das einfach: die 8 Bytes werden durchgetaktet und per Latch-Flanke auf die Ausgänge der Schieberegister geschalten. Jetzt könnten die Dinger ganz leicht neue Werte in den Serial-Buffer schreiben (wenn es eben - rein hypothetisch - bidirektionale Schieberegister wären). Mit den folgenden Taktflanken kann sich der Master dann die Antwortdaten zurück holen... Mit Microcontrollern im SPI-Slave-Modus wird das schwieriger. Ich habe gerade ein PIC-Datasheet durch und scheinbar funktionert SS nicht wie ein Latch Clock. Anstelle des "Annehmens" von den Daten im Shift-Buffer wird die gesamte SPI-Hardware mit SS erst angeschalten. Die Folge: ohne SS-Signal zerschellt der Datenstrom schon am ersten Slave in der Kette; und mit SS-Signal wird nach jedem Byte ein Empfangsinterrupt ausgelöst. Da aber kein Slave weiß, wie viele Slaves in der Kette liegen, kann er auch nicht wissen, wie viele Interrupts in der DaisyChain er abwarten muss, bevor seine Daten im Buffer anliegen. Schlimmer noch: durch das zu häufige Rückschreiben seiner Antwortdaten korrumpiert er den Datenstrom an seine Nachfolger. Ich hoffe, ich konnte das Problem nachvollziehbar formulieren? Ist wohl ein rechter Kauderwelsch geworden... :) Ein Workaround wäre, die SS-Leitungen immer low (SPI aktiv) zu legen und die freigewordene Signalleitung vom Master zu den Slaves mit je einem von deren Interrupt-Pins zu verbinden. Jetzt ließe sich die beschriebene Funktionalität einfach manuell zusammenprogrammieren: anstelle des SPI-Interrupts wird einfach alle 8 Bytes der ext-Interrupt verwendet, um - wie beim Schieberegister-Latch - das jeweilige Byte aus dem Slave-Puffer in den lokalen Speicher zu kopieren (und vielleicht die Antwortdaten zurückzukopieren). Die urpsrünglichen SPI-Slave-Interrupts können dann deaktiviert/ignoriert werden. Ist das die Methode der Wahl oder gibt es eine elegantere Lösung (z.B. in Hardware)?
Es geht genaus, wie bei einem Schieberegister. Angenommen, es sind 8 Slave. Dann müssen diese zuerst ihre Sendebytes in ihr SPI-Data schreiben. Nun schiebt der Master 8 neue Bytes rein und damit liest er gleichzeitig diese vorbereiteten 8 Bytes aus. Die Slave haben danach je ein neuese Byte empfangen und der Master hat alle 8 Bytes der Slaves. Aber dazu muß natürlich bekannt sein, wieviel Slaves maximal in der Kette sind.
ja so will ich es haben. Der Master weiß natürlich, wie viele Slaves da sind, nur die einzelnen Slaves haben davon keine Ahnung. Geht das mit dem SS-Eingang der Slaves? Ich behaupte "nein", da: Wenn die SS-Eingänge auf high liegen, kann der Master keine Bytes durchschieben, die Schiebelogik ist deaktiviert. Also muss SS bei allen Slaves immer auf low (aktiv) liegen. Wenn das aber so ist, wie teilt der Master den Slaves dann mit, dass das "Eintakten" der Daten beendet ist?
Was spricht denn eigentlich dagegen, alle SPI-Slaves parallel an das Interface zu hängen und bei jeder Übertragung ein Adressen-Byte mitzugeben, welches den entsprechenden Slave auswählt? Dann bräuchtest du keinen SlaveSelect- oder Latch-Ausgang mehr, wodurch der Pin am Controller frei wird für andere Dinge. Die Lösung mit dem Interrupt-Pin würde aber genauso funktionieren. Die mit SS, wie du selbst schon festgestellt hast, leider nicht, wenn die SPI-Transmitter der Slaves ohne SS abgeschaltet werden. Gruß Jonathan
Danke! Beides gute Hinweise! Ich verbinde jetzt mal den Interrupt Pin. Dann kann ich mir überlegen, wie es am Ende realisiert wird. Gegen die Adressierung könnte sprechen, dass dafür jeder Slave wieder eine bestimmte Adresse braucht, auf die er anspringt. Das ist aber wieder eine Art der "zentralen Information", die ich dem Slave nicht mitgeben (müssen) möchte. mal sehen... danke!
A. S. schrieb: > Also muss SS bei allen Slaves immer auf low (aktiv) liegen. Nein. SS = low 8 Bytes durchschieben SS = high. Die Slave legen SS mit auf einem Interrupt, dann wissen sie, wann Ende ist und können die Bytes lesen und neue reinschreiben.
Peter Dannegger schrieb: > Die Slave legen SS mit auf einem Interrupt, dann wissen sie, wann Ende > ist und können die Bytes lesen und neue reinschreiben. Stimmt, das wäre auch eine Möglichkeit, daran habe ich nicht gedacht. A. S. schrieb: > Gegen die Adressierung könnte sprechen, dass dafür jeder Slave wieder > eine bestimmte Adresse braucht, auf die er anspringt. Das ist aber > wieder eine Art der "zentralen Information", die ich dem Slave nicht > mitgeben (müssen) möchte. Wenn du es dann tatsächlich mit Adressen machst, kannst du ja dem ersten Slave per Hardware sagen (1 Pin auf Masse o.ä.), er soll sich beim Poweron eine Adresse vom Master holen, dann sagt dieser Slave dem nächsten, er soll sich auch eine Adresse holen (legt dessen Pin einfach auch auf Masse), usw., bis der letzte Slave seine Adresse hat. Damit kann der Master auch gleichzeitig feststellen, wie viele Slaves existieren. Gruß Jonathan
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.