Verständnisfrage SPI

Hallo,

ich hab vor einiger Zeit schon mal ADUs mit nem ATmega16 per SPI angesprochen. Das war aber immer nur ein ADU an einem ATmega16.

Jetzt habe ich eine etwas andere Aufgabe:

Ein Prozessor (vermutlich ATmega128) soll mit mehreren (1-8) ATmega8 Daten austauschen. Meine erste Idee war eine Ringleitung per UART, also ATmega128 sendet an 1. ATmega8. Dieser sendet an den 2. ATmega8 usw. bis zum letzten. Der letzte sendet wieder an den ATmega128.

Sowas habe ich schon mit 8031 Prozessoren realisiert. Nachteil ist aber, dass ich ein UART "verliere", den ich in dem Projekt eventuell noch benötige.

Der zweite Nachteil ist mechanischer Natur. Ich wollte die Slave-CPUs stapel, d.h. auf der Platine des Mega128 einen Pfostenverbinder und dann so ähnlich wie bei PC104 die Platinen stapeln (aber mit viel weniger Pins).

Die Ringleitung kann ich dann aber nicht ohne zusätzliche Umschalter/Jumper durchschleifen. Deshalb die Idee, einen BUS einzusetzen. Die Platinen können dann einfach gestapelt werden und man muss nur eine Adresse einstellen, z.B. über 4 DIP-Switches.

Wie beschrieben ist der Abstand zwischen den Busteilnehmern sehr kurz, ca. 15mm je Etage.

Jetzt habe ich mir die Doku zu SPI angesehen und dabei festgestellt, dass ich dort entweder die SS* Leitungen schalten muss, oder MOSI und MISO durchschleifen. Damit habe ich dann dasselbe Problem, wie beim UART.

Deshalb habe ich folgende Frage: Könnte man nicht die Slaves so beschalten, dass SS*, MISO, MOSI und SCK einen 3.Leitungs-Bus bilden. Die Slaves müssten so konfiguriert werden, dass MISO zunächst auf Tristate bleibt und erst dann aktiv wird, wenn ein Adressbyte empfangen wurde. Also ähnlich wie bei I2C.

Ich stelle mir das vereinfacht so vor: Master setzt SS* auf aktiv (0) und sendet ein Adressbyte. Die Slaves lesen das Adressbytes und der angesprochene Slave schaltet MISO auf aktiv und sendet mit den folgenden Takten die Daten an den Master.

Der Master muss nicht viele Kommandos senden. deshalb könnte man das so definieren, dass es sich um ein Adressbyte handelt, wenn Bit7=1 ist. Wenn Daten vom Master an einen Slave geschickt werden sollen, kann man diese auf 2 Bytes aufteilen. Oder man nimmt die ersten 4 Bits für die Adresse und die nächsten 4 Bits für die Daten. Andererseits wäre auch eine Telegrammstruktur mit Startzeichen+Adresse+Daten möglich.

Geht das so, oder habe ich etwas grundlegendes vergessen?

Wobei, wenn ich genau überlege wäre es vieleicht doch nicht verkehrt, die SS* Leitungen sternförmig auszulegen...

Gruß

Stefan

Reply to
Stefan
Loading thread data ...

Das ist bei SPI so eigentlich nicht vorgesehen, die Transfers sind normal immer bidirektional ab dem ersten Bit. Sobald du /SS aktivierst beginnt ein Slave MISO zu treiben, das gibt also eine Kollision wenn du mehrere Slaves gleichzeitig aktivierst.

Du koenntest es aber schon auch so aufbauen, dass die Slaves nur auf Befehl MISO treiben. Z.B. via externem Tristate-Treiber an MISO (der erst nach Validierung der eigenen Adresse vom Slave aktiviert wird).

Oder du addressierst die Slaves binaer, dann reichen 3 Pins fuer 7 Slaves (8 falls "bus free" nicht erforderlich ist). Die Decodierung koennte der Slave AVR z.B. via Pin Change Interrupt selbst machen und dann bei Bedarf sein eigenes /SS runterziehen. Dein Protokoll muss ihm halt genug Zeit dazu lassen.

Micha

Reply to
Michael Baeuerle

Ah, 8051 Architektur, schoen :-)

Man kann einen UART auch per bit-banging machen.

Ich nehme mal an dass es aus irgendeinem Grund 1:1 durchgehende Header sein muessen. Mit SMT Headers und beidseitiger Bestueckung wuerde sich dieses Problem in Wohlgefallen aufloesen, da kannst Du analog wie auch digital Daisy Chain machen.

Klar geht das, aber dann hast Du immer noch diese DIP Switches.

Warum nicht SS auf drei Pins verteilen? Dann hast Du Deine acht Adressen und nur der uC mit der passenden Adresse bedient MISO waehren alle anderen inklusive des sendenen uC MISO solange auf Input oder Tri-State lassen.

Falls drei Pins fuer Chip Select zuviel sind dann stattdessen einen Pegel senden und ueber ADC Input oder Dual-Slope messen lassen. So entscheiden die uC anhand der gemessenen Spannung wer dran ist und auf MISO gehen darf. Braucht nur einen Pin.

Warum? Habe ich nie gemacht. Zumal das bei Dir acht Leitungen waeren, ziemliche Verschwendung.

Weiter gaebe es noch esoterische Methoden um z.B. die Notwendigkeit von DIP Switches auch bei 1:1 Headers zu umschiffen. Kleine Chip-Induktivitaeten oder Piezos pulsen und der naechste uC erkennt sequenziell (sequentiell?) einfach aufgrund seiner Position im Stapel wann er dran ist. Wenn beidseitige Bestueckung moeglich ist tut es auch eine LED oben und eine Photodiode unten. Mache aber zur Sicherheit eine Address-Reset Line rein, oder eine entsprechende Funktion als Datenwort welches ueber MOSI rausgeht. So haettest Du eine Daisy Chain fuer die Adresse. Sowas geht natuerlich auch fuer MOSI und MISO aber da brauchst Du je zwei und dann waere auch kein SPI mehr noetig.

--
Gruesse, Joerg

http://www.analogconsultants.com/
Reply to
Joerg

Stefan schrieb:

Hallo,

wenn Daten austauschen Datenübertragung in beiden Richtungen bedeutet, dann müssen Daten die der erste ATmega8 zum ATmega128 schicken will durch alle anderen ATmega8 hindurchgeschickt werden. Daten die der ATmega128 zum letzten ATmega8 schicken will müssen durch alle anderen davor hindurch. Willst Du das wirklich so haben?

Bye

Reply to
Uwe Hercksen

Bei vielen µC (u.a. AVR) auch ohne externen Tristate-Buffer möglich. Pins können hochohmig geschaltet werden.

Gruß Thomas

Reply to
Thomas Stegemann

Das geht bei den AVRs leider nur mit Soft-SPI, denn weder das dedizierte SPI noch USART im SPI-Mode noch USI sehen diese Betriebsart vor, im Gegenteil, die vorhandene Hardware schließt sie sogar weitgehend aus. Klar mit der Nase durchs Knie in den Rücken kann man schon irgendwas Funktionierendes in dieser Richtung gebacken bekommen, aber die Vorteile der Hardwareunterstützung gehen dabei weitgehend verloren.

Aber wenn du schon I2C erwähnst: Warum verwendest du es denn nicht?

Jeder ATMega hat's und auch etliche ATtinys. Scheint mir für deine Anwendung sowieso deutlich besser geeignet, denn hoher Durchsatz kann ja wohl angesichts der geringen sinnvoll einsetzbaren Wandlerrate und

-Auflösung eh' kaum gefordert sein...

Reply to
Heiko Nocon

Am Mon, 02 Apr 2012 16:26:26 +0200 schrieb Stefan:

[SPI Daisy-Chain Probleme]

i2c wär keine Alternative?

Grüße, Peter

Reply to
Peter Tarkus

Stimmt, hab ich auch schon überlegt bzw. hab sowas auch schon programmiert. Das geht aber nur bis zu einer gewissen Baudrate. Ich würde den Bus gerne etwas schneller machen. Aber ich könnte ein UART verwenden und bei Bedarf einen zusätzlichen UART mit 9K6 per Software realisieren.

Ja, wenn der ATmega128 auf Pin 1 sendet und der 1. ATmega8 auf Pin 1 emfängt sollte er wieder auf Pin 1 senden, damit der 2. ATmega8 wieder auf PIN 1 lesen kann. Der letzte bekommt einen Jumper von Pin 1 nach Pin

2 und Pin 2 ist von oben nach unten durchgeschleift. So hängen dann alle Slaves hintereinander. Ich hatte schon überlegt, einen Draht von einer Ebene zur nächsten über Wago-Federklemmen zu stöpseln. Aber der Tip mit SMT Headern gefällt mir besser.

Och nö, dass lass ich lieber ;-)

Je mehr ich drüber nachdenke, gefällt mir die UART Lösung mit Ringleitung immer mehr. Ich brauche die Slaves nur stapeln und die Adresse ergibt sich automatisch aus der Reihenfolge, also keine Jumper oder DIP-Switches. Der Nachteil, dass ein UART "verloren" geht ist wohl zu verschmerzen. Das Gerät soll später RS232, RS485 oder Ethernet (per X-Port?) bekommen. Aber momentan sehe ich noch keine Notwendigkeit, diese gleichzeitig zur Verfügung zu stellen, d.h. entweder RS232 oder RS485 oder Ethernet.

Gruß

Stefan

Reply to
Stefan

Oder die Version mit den Pulsen ueber eine ungeschirmte Induktivitaet. Da kriegen potenzielle Abkupferer die Pimpanellen weil sie kaum rausbekommen werden wie es funktioniert. Fuer ein sehr kostensensitives Massenprodukt waere es das einzig senkrechte, u.U. sogar mit Print-Spule zum Nulltarif.

Aber eben nur mit beidseitiger Bestueckung von Stecker/Buchsen. Muss nicht unbedingt SMT sind, aber eine muss unten bestueckt werden. Es geht nur mit irgendeiner Art der sequenziellen Signalisierung zumindest fuer die Position im Stapel wenn Du DIP-Switches vermeiden moechtest. Ich vermeide die grundsaetzlich weil alles mechanische zu schnell kaputtgehen oder fehlbedient werden kann.

Meist kommt eines Tages der "Feature Creep" und man muss eine weitere Schnittstelle aus dem Hut zaubern. Laut Murphy passiert sowas kurz vor dem geplanten Sommerurlaub. BT.

--
Gruesse, Joerg

http://www.analogconsultants.com/
Reply to
Joerg

Am 02.04.2012 18:32, schrieb Thomas Stegemann:

Dann muss man aber SPI per "bitbanging" realisieren.

Reply to
Heiko Lechner

Stefanschrieb: "

Verwende die UART als 1-Draht-Schnittstelle (Open-Collector) und verbinde alle Controller damit. Kollisionserkennung wie bei CAN/LIN/K-Line, also ein Byte abschicken und das dabei empfangene Byte mit dem gesendeten vergleichen. Dominanter Pegel überschreibt rezessiven Pegel usw. .. Findet man alles im Netz und wird seit vielen Jahren in Fahrzeugen verwendet.

Dirk

Reply to
Dirk Ruth

Am 02.04.2012 16:26, schrieb Stefan:

Nur der Vollständigkeit halber: Den "Multi Processor Communication Mode" (MPCMn) der USARTs hast du dir den in den Datasheets durchgelesen? Sieht auf den ersten Blick doch genau wie das aus was du suchst...

Andreas

Reply to
Andreas Koch

Stefan :

Hardwareunterstützung brauchst Du eigentlich immer. Bei asynchronen Signalen (also RS232 ähnliches oder auch 1 wire) die mit festen Zeiten für die Bits arbeiten, brauchst Du entweder einen Uart oder einen Timer mit Capture Eingang der die Zeiten aussmessen kann. Mit reiner BitBang-Software lässt sich sowas nur langsam realisieren, weil die Software - so lange wie sie auf Empfang geschaltet ist - den kompletten Prozessor blockiert. Auch ein einfacher Port-Interrupt hilft wenig - weil die Interrupt-Annahme-Zeit da oft in Größenordung von ein paar bits liegt. (Es sei denn man lebt mit ner Baudrate von 1200baud oder sowas und muss drauf achten, dass es ein hochpriorisierter nicht von anderen unterbrechbarer Interrupt ist).

Bei den synchronen Slaves (SPI oder I2C) ist ein spezieller Uart auch nicht schlecht. Man muss ja an jedem Taktwechsel das Datenbit ablesen, das würde per Portinterrupt gehen, aber auch nur langsam (wegen der Interrupt-Latenzen, die auch davon abhängen wie lange der Code Interrupts sperrt).

Letztlich handelt man sich mit Software-Slaves eigentlich immer nur Ärger ein, die sich auf die restliche Software auswirkt, je komplexer die ist, um so schlimmer. Dann lieber gleich einen vernüftigen Controller wählen, der nen zusätzlichen Uart drin hat.

M.

Reply to
Matthias Weingart

So hatte ich es auch in Erinnerung. Seltsam ist dann aber dieses Zitat aus dem Datasheet des mega128: | | MISO ­ Port B, Bit 3 | [...] | When the SPI is enabled as a slave, the data direction of this pin | is controlled by DDB3. When the pin is forced to be an input, the | pull-up can still be controlled by the PORTB3 bit.

Demnach sollte es ja eigentlich funktionieren. Die Beschreibungen auf Seite 70 ff. ("Alternate Port Functions") und Table 32 widersprechen aber obiger Aussage. Wenn man die dortige Logik nimmt, duerfte sich im slave mode der Treiberstatus von MISO nie aendern und muesste immer von DDB3 abhaengen (also entweder immer Input oder immer Output, egal was man mit /SS macht) => ???

Micha

Reply to
Michael Baeuerle

Am 02.04.2012 22:05, schrieb Heiko Lechner:

Wieso denn? Der Atmel ist zwar nicht so flexibel wie z.B. der MSP430, aber es ist machbar mit den internen Treibern und dem internen SPI. Ohne Bitbanging. Siehe Atmega-Datenblatt "DOC2466" Seite 136.

Eigentlich möchte ich Stefan keine Antwort geben. Wer keine gültige Antwortadresse angibt, möchte gar keine Antworten. Und dann fälscht er auch noch eine.

MOSI->----------+--------+---------+ Master Slave1 Slave2 Slave3 MISO-

Reply to
Gunther Mannigel

Am 03.04.2012 11:34, schrieb Gunther Mannigel:

Jau, hast recht.

Reply to
Heiko Lechner

Am 03.04.2012 10:57, schrieb Michael Baeuerle:

Da steht ja "DDOE = SPE & MSTR" und DDOE steuert den Mux des DDR override. Ist "DDOE = 0" (was ja im Slave- Betrieb vorliegt), dann wird der DDR- Wert nicht überschrieben. Ist "DDOE = 1", dann wird DDR "immer mit 0 überschrieben" -> immer input. Also bei Slave hat man wohl drei Optionen: senden lassen, Pullup oder nix.

Reply to
Heiko Lechner

So verstehe ich das auch.

Genau, das ist fuer den Master mode (MSTR = 1 und SPE = 1) ja auch richtig.

Nach Figure 33 muesste der MISO Pin im Slave mode dann allerdings

*permanent* niederohmig sein solange man DDB3 auf 1 gesetzt hat. Das wuerde so mit mehreren Slaves aber nicht funktionieren und ist auch anders dokumentiert. Zitat aus dem SPI Kapitel: | | When configured as a Slave, the SPI interface will remain sleeping with | MISO tri-stated as long as the SS pin is driven high.

Diese Logik ist mit der in Figure 33 abgebildeten Schaltung aber nicht moeglich. Damit es keine Kollision der Slaves auf MISO gibt muss die SPI den MISO Treiber selbst steuern (via /SS), dieser Teil scheint dort zu fehlen.

Micha

Reply to
Michael Baeuerle

Am 03.04.2012 15:27, schrieb Michael Baeuerle:

Das würde ich jetzt so unterschreiben ;)

Reply to
Heiko Lechner

Ob die besagte Kontruktion ohne externen Treiber funktioniert haengt nun leider genau von dem fehlenden Teil ab. Falls die SPI zwischen High-Z und dem Wert von DDB3 umschaltet, dann wuerde es ohne funktionieren. Es ist vmtl. auch so implementiert, anderenfalls wuerde der Wert von DDB3 nicht benutzt werden. Sie schreiben aber beim MISO Pin im Slave mode: "Data direction: user defined", das wuerde sonst keinen Sinn ergeben.

Micha

Reply to
Michael Baeuerle

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.