Hallo zusammen!
Ich arbeite im Moment an meiner Projektarbeit für die Technikerschule.
Inhalt dieses Projekt ist es u.a., eine Datenmenge durch ein System zu
senden, das kaskadierbar ist.
Wir haben uns dazu folgendes überlegt: Einen SPI-Bus im Stern aufzubauen
und erstmal über drei Bits im gesendeten Byte (die anderen 5 Bits
stellen die Information dar, die verarbeitet werden soll) eine
Adressierung vorzunehmen (ergäbe für den Anfang 8 Teilnehmer).
Jetzt aber die Preisfrage: Kann man überhaupt mehr als zwei Controller
via SPI Bus miteinander verbinden? Die Literatur die wir besitzen
(Günter Schmitt, µC-Technik mit Controllern der Atmel AVR-RISC-Familie),
sagt eindeutig, dass man das machen kann. Es finden sich aber nirgends
wirklich Beispiele, wo das schonmal praktiziert worden ist.
Also: Jeht dat? Und wer hat da Erfahrung mit und kann mir Tipps geben?
Beste Grüße,
Dennis
im Prinzip gibt es da 2 Möglichkeiten für dein Vorhaben.
1. Das ist die SPI SPEC Variante
Verbinde bei allen µC die Signale MISO, MOSI, CLOCK und zusätzlich vom
Master ein einzelnes Signal zu jedem µC um ihn anzusprechen(Chipselect).
Somit kann immer nur EIN µC angesprochen werden.
Skalierbar ist das nur soweit wie Pins für Chipselect verfügbar sind.
2. Variante
Die SPI ist nichts anderes als ein Schieberegister.
Schalte die µC in Reihe hintereinander.
Dann legts du im Ram 2 Stukturen an, die die Größe hat von "Anzahl der
µC" * "Registergröße" also zb 8µC mal 8 Bit(1 Byte) = 8 byte.
Stuktur 1 ==> TX ; Stuktur 2 ==> RX .
Somit kannst du dann über die Adressierung des Bytes den anzusprechenden
µC auswählen und mit Senden der vollständigen Struktur die Daten
durchschieben.
Skalierbarkeit ist Begrenzt durch die maximale Größe der TX und RX
Struktur und die benötigte Übertragungszeit. Diese Strukturgröße ist
Abhängig vom verfügbaren RAM.
Variante 1 läßt sich mit Hardwareschieberegistern für das Chipselect
ewig weiter ausbauen ;-). Das geht, wie auch Variante 2, auf Kosten des
effektiven Datendurchsatzes.
>Wir haben uns dazu folgendes überlegt: Einen SPI-Bus im Stern aufzubauen>und erstmal über drei Bits im gesendeten Byte (die anderen 5 Bits>stellen die Information dar, die verarbeitet werden soll) eine>Adressierung vorzunehmen (ergäbe für den Anfang 8 Teilnehmer).
Das geht leider nicht. Dazu müssten alle SPI Slaves
per Chip Select gleichzeitig aktiviert werden. Das dumme an der
Geschichte
ist, das dann alle SPI Slaves ihren Ausgang (MISO) aktivieren
und keiner mehr durchkommt weil die sich gegenseitig kurzschliessen.
Wenn keine Rückmeldung vom Slave erforderlich ist könnte es
aber so funktionieren.
Slaves ohne Rückmeldung sind doch eigentlich relativ sinnfrei. Statt des
SPI könnte man auch das UART nutzen, dort kann man duch geschicktes
Verschalten im Vollduplex über nur 2 oder im Halbduplex über nur eine
Leitung gegenüber Masse senden und empfangen. Die Geschwindigkeit wäre
hier maximal 1/8 Controller-Takt. Das Adressieren kann man über das 9-te
Bit machen, hierbei kann der MultiprocessorCommunicationMode verwendet
werden.
SPI als Interprozessorkommunikationsbus ist machbar. Einer muss den
Master spilen und den clock (SCK) vorgeben. Alle Schieberegister sind in
Serie. Dh Miso auf Mosi. Sinnvollerweise laufen eh alle CPUs am selben
clock. Nachteil des SPI ist dass er keinerlei Puffer hat. Mit zunehmend
schnellem Takt wird das Timing hart fur die CPU.
Hallo! :)
OK, also den Stern dann nicht. Alles in Serie. Ist auch OK.
Aber jetzt zur Steuerung:
Wenn die alle in Serie geschaltet sind, aber nur EINER der µC das
Datenpaket erhalten soll, kann man doch wie schon von mir angedeutet,
eine Adressierung über Bits des verschickten Paketes machen, oder?
Das Ganze soll folgendermaßen funktionieren:
Ein Micrcontroller (immer derselbe) erhält eine Anfrage (Taster an
Portpin). Insgesamt sind 8 Taster an ihm angeschlossen. Je nachdem, über
welchen Taster eine Anfrage gemacht wird, braucht er von einem
bestimmten Controller ein Meßergebnis. Wie steuer ich dann den Bus? wann
muss wer Slave sein und wann Master oder ändert sich das nie? Und kann
ich dann überhaupt nur EIN Byte versenden? weil jedes Mal, wenn ein
Controller was empfängt, schickt er doch gleichzeitig was in den Bus
zurück, oder? Also wären dann ja schon zwei Bytes unterwegs, oder?
Klärt mich mal bitte auf. Die SAche ist mir trotz Literatur noch nicht
ganz klar!
Besten Dank für Eure bisherige Hilfe!
Take care,
DEnnis
Na, du kannst mit dem chipselect ja signalisieren welcher nun dran ist.
Du kannst zB 8 bytes durchschieben und dann allen gleichzeitig den
chipselect geben. Dann hat jeder sein Byte empfangen.
Ah so! Ja klar! Klingt ja einfach! Also könnte ich ja quasi einen Master
definieren und die anderen Controller als Slaves laufen lassen. Wenn der
Master eine Info benötigt, signalisiert er das über den Chipselect, läßt
sich die 8Bytes seiner Slaves schicken und selektiert dann selber,
welches er davon benötigt.
Habe ich das nun richtig verstanden? :)
DANK!!!
Dennis
Ich glaube, SPI ist für diese Anwendung letzlich nur ein Gewürge: viel
Aufwand mit zweifelhaftem Resultat.
Ein Bussystem per UART (z.B. RS485) ist einfacher zu erstellen und zu
erweitern. Die Erfahrungen damit lassen sich später auch für andere
Anwendungen nutzen.
Genau. Das Problem bei SPI, daß man auf das Rausschieben des Bytes
warten muß, bevor ein nächstes geschoben werden kann, ist beim UART
eleganter gelöst und der Controller hat mehr freie Zeit.
Bei SPI verlaesst man die Leiterplatte nicht, resp ueberschreitet 20cm
nicht, wohingegen ein UART bei diesen kurzen distanzen uebertrieben ist.
Ein UART nimmt man fuer externe Anbindungen Auch ein UART generiert ein
Interrupt pro Byte und das muss man holen bevor das Naechste kommt.
>Auch ein UART generiert ein Interrupt pro Byte und das muss man holen >bevor das
Naechste kommt.
Wobei ich immer das Problem habe, das es so lange dauert, bis das
nächste Byte kommt :-)
UART nehme ich auch auf Leiterplattenebene, da die Übertragung nicht
blockiert werden kann, wie es z.B. bei IIC allein schon durch ein
korruptes Handshake passieren kann. Und da selbst kleine ATtiny2313
schon den Multiprozessormodus unterstützen, ist auch die Belastung durch
UART-Interrupts gering; nur der adressierte Teilnehmer muß die Daten
empfangen und auswerten.
holger wrote:
> Das geht leider nicht. Dazu müssten alle SPI Slaves> per Chip Select gleichzeitig aktiviert werden. Das dumme an der> Geschichte> ist, das dann alle SPI Slaves ihren Ausgang (MISO) aktivieren> und keiner mehr durchkommt weil die sich gegenseitig kurzschliessen.
Das geht nur bei den AVRs nicht.
Bei den Atmel AT89LP4052 geht das, die können nämlich MISO abschalten
und nach dem Adreßbyte schaltet nur der adressierte MC sein MISO ein.
Man kann natürlich nicht innerhalb eines Bytes umschalten.
Außerdem haben sie einen Sendepuffer und Interruptprioritäten. D.h. der
Master kann Fullspeed die Daten empfangen.
Bei den AVRs muß der Master nach jedem Byte lange warten oder ne extra
Handshakeleitung abfragen.
Peter
Hallo :)
Also wir werden das auf jeden Fall über SPI machen. Die Controller haben
eh nicht viel zu tun, also ist das Warten auf das Ende einer Übertragung
in diesem Fall völlig schnurz :)
Aber eine kleine Sache noch:
Die Übertragung wird durch den Master dadurch gestartet, in dem er den
SS-Portpin auf LOW zieht. Wenn ich aber wie in unserem Fall mehrere
Slaves habe, dann könnte ich doch einfach eine Adressierung der anderen
Slaves dadurch vornehmen, in dem ich die SS-Portpinne der Slaves mit
anderen unbelegten Portpinnen des Masters verbinde, oder? So kann ich
doch über Code bestimmen, welchen Portpin der Master auf LOW zieht und
damit einem bestimmten Slave signalisieren, dass nun eine Übertragung
startet. Weil die Controller haben ja nur einen SS-Pin ...
Übrigens danke für Eure Anregungen. Aber es hat mehrere Gründe, warum
wir das mit SPI machen. Dass es einfachere und schnellere Varianten
gibt, ist klar. :)
Grüße,
Dennis
@Dennis
Gensauso wie du es im Post von 12:49 beschrieben hast funktioniert das.
MISO, MOSI, SCLK von allen Slaves und Master miteinander verbinden; Das
ist keine Serienschaltung sondern Parallel.
Und dazu die Chipselect, oder SS, im Stern vom Master zu den einzelnen
Slaves.
Dazu benötigst du am Master für jeden Slave einen eigenen Portpin der am
Slave als Chipselect funktioniert.
Der "Stern" ist NUR für die Chipselselect,SS
Die Übertragung startet aber nicht mit Chipselect. Dieser Pin ist nur um
das SPI interface des Slave aktiv zuschalten und das der Slave
informiert wird, sein Datenbyte in den Ausgangspuffer legt.
Die Übertragung startet mit dem ersten Clock vom Master.
Ja okay. Das habe ich nun verstanden :) Danke!
Laut Holger (03.1. 22:14) sind die MISO zwangsgesteuert. Im Datenblatt
steht aber was anderes. Da steht drin, dass man per Software bestimmen
kann, welchen Zustand die Ausgänge haben (Seite 66 unten:
"When the SPI is enabled as a Slave, the data direction of this pin is
controlled by DDB6"
Also lässt sich das doch im Code anhand des Zustands vom Slave-Select
Pin abfragen, oder? Und weil die Übertragung mit dem Clock-Signal
startet und dieses mindestens 4mal langsamer ist als der Prozessortakt,
kann man diese Pinne doch ohne Probleme über DDb6 steuern, oder?
Kann ich nun Stern bauen oder nicht? ;)
>Warum eigentlich nicht TWI einsetzen? das ist doch für bis zu 127>Teilnehmer ausgelegt...
Les doch einfach mal das Topic ganz durch.
Er hat es doch schon mehrfach gesagt.
Es soll definitiv per SPI gemacht werden also erübrigt sich die
Diskussion darüber welchen Bus man nehmen sollte und welcher besser sein
könnte usw.
Hey :)
Es ist keine berechtigte Frage. Wie Du gelesen hast, ist das meine
Projektarbeit. Und wenn das eine gewählte Vorgabe ist, dann ist das halt
so, gell ;)
Aber ich bin immer noch keinen Schritt weiter was die Verbindung
betrifft.
@Dennis
MISO, MOSI, SCLK werden von SPI interface in Hardware gesteuert.
Configuriere diese PINS (an Master und Slave) und den SS (nur an den
slave) für SPI Funktionalität, NICHT als IO Pins und ansonsten lass die
Finger von diesen Pins, es sei denn du willst die SPI in Software
darstellen.
Chipselect oder auch SS genannt werden VOR der Kommunikation vom Master
auf Aktiv gesetzt. In der Regel ist das LOW signal, muss aber nicht.
Und nach dem letzten Takt des letzten Bytes auf der SCLK Leitung wieder
auf Passiv gesetzt.
Wenn also zu einem Slave zb 5 Bytes gesendet werden sollen, dann ist
folgenden Ablauf:
1. Chicselect auf Passiv für alle Slave ( sollte Immer so sein, wenn
keine Kommunukation läuft)
2. Chipselect auf Aktiv für den ausgewählten Slave
3. Master und Slave legen Byte 1 in den Ausgansbuffer.
4. Der Master taktet das Byte über SCLK raus.
5. Master und Slave lesen Byte 1 aus dem Eingangsbuffer
6. Master und Slave legen Byte 2 in den Ausgansbuffer
7. Der Master taktet das Byte über SCLK raus.
8. Master und Slave lesen Byte 2 aus dem Eingangsbuffer
9. Master und Slave legen Byte 3 in den Ausgansbuffer
10. Der Master taktet das Byte über SCLK raus.
11. Master und Slave lesen Byte 3 aus dem Eingangsbuffer
12. Master und Slave legen Byte 4 in den Ausgansbuffer
13. Der Master taktet das Byte über SCLK raus.
14. Master und Slave lesen Byte 4 aus dem Eingangsbuffer
15. Master und Slave legen Byte 5 in den Ausgansbuffer
16. Der Master taktet das Byte über SCLK raus.
17. Master und Slave lesen Byte 4 aus dem Eingangsbuffer
18. Chipselect für den ausgewähten Slave auf Passiv
19. ENDE
@Ralph:
Jau danke! Das hat mir weitergeholfen! Da Du über Chipselect einen Slave
anwählst, kann der Bus nur in Stern geschaltet sein. Also geht das so!
Und der Ablauf ist mir nun auch klar!
Vielen Dank! ;)