Hallo,
ich beabsichtige zwei Atmega32 miteinander zu verbinden. Ein Atmega
arbeitet zentrale Prozesse ab und koorinidert den Datentransfer. Der
zweite Atmega soll nur mit einer Unteraufgabe betraut werden, die recht
viele Rechenzyklen frisst.
Meine Frage ist nun, wie ich diese Verbindung möglichst einfach, aber
stabil umsetzen kann. Das Datenvolumen besteht nur aus Steuerdaten und
kann sicher mit etwa 10-20 kBit/s abgearbeitet werden. Der Transfer ist
zunächst monodirektional vom Master zum Slave. Zudem ist der Transfer
nur bedingt zeitkritisch (Bereich etwa 1ms). Es sollte aber nicht zu
Datenverlusten kommen.
Mir bekannte Möglichkeiten: SPI, UART oder I2C. Bislang bevorzuge ich
SPI oder UART.
Welche Kommunikationsschnittstelle ist nach eurer Meinung die
sicherste/einfachste/robusteste Lösung für das obige Problem? Bisher
habe ich Erfahrungen mit UART und SPI uC/uC Kommunikation gesammelt.
Leider waren diese Verbindungen nicht immer vollständig stabil, so dass
ich bereits überlegt habe, zwei Ports für einen generellen 8-Bit
Daten-/Adressbus zu verwenden.
Mit Gruss
Mike
UART ist zwar möglich, hat hier aber keine Vorteile, sondern ist eher
für eine Datenverbindung zu einem etwas entfernteren Partner gedacht.
Für die Kommunikation innerhalb einer Schaltung ist I²C entwickelt, aber
wenn es nur um zwei Partner geht, würde ich SPI nehmen.
Vorletztes Jahr habe ich einen ATmega88 mit 12 ATtiny24 über SPI
verbunden. Der ATmega88 war der Master, die ATtinys antworteten.
Allerdings waren alle Controller durch Optokoppler voneinander
galvanisch getrennt, was die Datenrate auf 17 KBit/s (brutto) senkte.
Dabei waren die Optokoppler der Flaschenhals.
Mike schrieb:> Leider waren diese Verbindungen nicht immer vollständig stabil,
Das musste dann aber am Protokoll liegen.
Mike schrieb:> so dass> ich bereits überlegt habe, zwei Ports für einen generellen 8-Bit> Daten-/Adressbus zu verwenden.
Das ist durchaus eine Möglichkeit, die Du dann aber vollständig in
Software abbilden musst. Eine Hardware-Unterstützung gibt es hier ja
nicht. Es gibt übrigens einige PICs (z. B. PIC16C74B), bei denen sowas
vorbereitet ist. Dort heißt das PSP ("Parallel Slave Port").
Ich würde SPI verwenden und mir Gedanken zu einem vernünftigen Protokoll
mit Time-Out und Fehlerbehandlung machen.
Mike schrieb:> Der Transfer ist> zunächst monodirektional vom Master zum Slave.
Das wird er wohl nicht bleiben. Sicher wird doch der Master vom Slave
gelegentlich zumindest wissen wollen, ob er noch lebt und was arbeitet,
oder nur unnütz Strom verbraucht?
> Welche Kommunikationsschnittstelle ist nach eurer Meinung die> sicherste/einfachste/robusteste Lösung für das obige Problem?
UART natürlich. Da Du nur zwei Kommunikationspartner hast, können diese
über UART bequem bidirektional kommunizieren. Du musst weder
synchronisieren, noch pollen. Das macht die Sache viel einfacher.
> Bisher> habe ich Erfahrungen mit UART und SPI uC/uC Kommunikation gesammelt.> Leider waren diese Verbindungen nicht immer vollständig stabil,
Das muss an Deinem Code gelegen haben. UART und SPI-Verbindungen
funktionieren über Jahre stabil, wenn es
1) ein brauchbares Protokoll gibt und
2) dieses fehlerfrei implementiert ist.
SPI hat bei AVRs recht hässliche Zeitbedingungen auf der Slave-Seite.
UART ist deutlich einfacher und relaxter. I2C bietet sich an wenn man es
sowieso schon verwendet oder die UARTs nicht zur Verfügung stehen.
> Leider waren diese Verbindungen nicht immer vollständig stabil
Wenn UART auf kurze Distanz instabil ist, dann ist es vmtl. jede andere
Kommunikation auch, ausgenommen "Schwarze Magie" ab V3.1. Soll heissen:
Du solltest mal überlegen warum instabil. Datenverluste? Mit per
Interrupt betriebener UART gibts die nur bei Softwarefehler oder bei
Unfug wie einem wait_ms(10) in der ISR.
Mike schrieb:> Bisher> habe ich Erfahrungen mit UART und SPI uC/uC Kommunikation gesammelt.> Leider waren diese Verbindungen nicht immer vollständig stabil, so dass> ich bereits überlegt habe, zwei Ports für einen generellen 8-Bit> Daten-/Adressbus zu verwenden.
Auf kurzen Strecken, z.B. auf einem Board, darf es es dabei keine
Probleme geben, wenn alles richtig designed ist. Wenn eine serielle
Verbindung wie SPI nicht stabil ist, ist es eine parallele erst recht
nicht. Eine SD Card trommelt die Daten mit bis zu 40MHz über eine
SPI-ähnliche Verbindung, und das ohne spezielle Treiberbausteine.
I2C hat den Vorteil, daß mehrere Bausteine adressiert werden können.
Dies zählt bei nur zwei Bausteinen nicht. SPI erreicht höhere Datenraten
und ist daher das Mittel der Wahl. Ich kenne jetzt die Atmega32 nicht,
gehe aber davon aus, daß SPI in Hardware unterstützt wird. Man kann auch
noch zusätzliche Leitungen verwenden, damit die Prozessoren sich
gegenseitig einen Interupt schicken können.
MfG Klaus
> Ich kenne jetzt die Atmega32 nicht,> gehe aber davon aus, daß SPI in Hardware unterstützt wird.
Das schon, es ist aber nur ein einfaches Schieberegister mit zwar einem
Empfangspuffer, aber ohne jeden Sendepuffer. Man muss sich also ein
recht gut zeitlich definiertes Protokoll überlegen, damit der Slave auf
eingehende Daten überhaupt antworten kann, denn er kann nur bei
inaktivem SPI ins Transmit-Register schreiben. Summarum landet man
ausserdem bei 2 Leitungen für UART und 5 für SPI.
A. K. schrieb:> Das schon, es ist aber nur ein einfaches Schieberegister mit zwar einem> Empfangspuffer, aber ohne jeden Sendepuffer.
D.h. der Master bekommt erst mit dem zweiten gesendeten Byte sinnvolle
Daten zurück? Das ist aber häufig so bei SPI.
MfG Klaus
Klaus schrieb:> D.h. der Master bekommt erst mit dem zweiten gesendeten Byte sinnvolle> Daten zurück? Das ist aber häufig so bei SPI.
Ja, aber das ist auch nicht wirklich das Problem.
Nur entsteht beim ein Slave ein arg hässliches Zeitproblem, weil er auf
das Transmit-Register nur zwischen den Byte-Übertragungen zugreifen
kann, nicht währenddessen. Er kriegt sonst ein beleidigtes WCOL um die
Ohren gehauen. Der Master muss also nach seinen gesendeten Bytes
explizit ausreichend Zeit lassen, damit der Slave überhaupt seine
Antwort reinstellen kann, bevor der Master diese durchtaktet.
Muss der Slave mehrere Bytes antworten, dann muss zwischen jedem davon
Zeit gelassen werden, es sei denn der Slave hockt mit abgeschalteten
Interrupts pollend an der Strippe und erwischt so die verdammt kurze
Zeit zwischen zwei Bytes.
Wenn man also mit SPI eine sichere Kommunikation aufbauen will, dann
kann man entweder einen separaten Hardware-Handshake verwenden. Oder man
definiert ein spezielles Übertragungsprotokoll, beispielsweise indem der
Master ein mit seinem vorher gesendeten Byte identisches Antwort-Byte
als Signal für "bin beschäftigt" sieht und darauf passend reagiert.
Jedenfalls ist ein SPI Slave mit AVR nicht so einfach wie es zunächst
aussehen mag. Man muss deutlich Überlegung reinstecken, um
sicherzustellen, dass es zuverlässig funktioniert.
Auf kurze Entfernung, z.B. auf einer Platine, ist der UART die geeignete
Wahl. Es besteht sogar die Möglichkeit, z.B. ein kleines Ringnetz mit
mehr als 2 Kommunikationspartnern zu gestalten, in dem alle ringsum
durchgeschleift sind, wobei man dann über ein kleines Protokoll zu jeder
Zeit jeden direkt ansprechen kann.
Der UART ist einfachst in der Handhabung, erzeugt am Ende eines
übertragenen Bytes einen Interrupt, und FIFOs hat man als Standard auch
noch irgendwo als Software herum liegen.
Und zwar habe ich hier so ein kleines System mit 3 gleichen Boards (µC
ist der SAB80C517A), die auf diese Art über LWL miteinander verbunden
sind. Das funktioniert da vorzüglich und schnell. Das Ringnetz ist rein
hardwaremäßig über einfache Logikgatter durchgeschleift, d.h., die Daten
gehen nicht durch die Kommunikationspartner selbst hindurch, sondern
daran vorbei. OK, es sind uralte Systeme mit alten Bausteinen. Aber der
UART gibt immerhin noch 1,5 Megabaud her, und die LWL-Bausteine spielen
das auch noch mit.
Klaus schrieb:> Klaus schrieb:>> Das klingt wirklich suboptimal.>>>> MfG Klaus>> War jemand dazwischen: bezieht sich auf SPI-Slave von A. K.>> MfG Klaus
Aah, OK.
Meines war nur mal ein gut funktionierendes Beispiel. Der SAB80C517A
hatte zu seiner Zeit als Schnittstellen auch nur 2 UARTs, sonst nichts.
Und dann macht man das Beste aus dem, was man hat.
>>Oktav Oschi schrieb:>> Ueberleg mal wie denn die Daten beim SPI zurueckkommen...>>Über die MISO Leitung, wie bei ADCs, SD-Karten, ...
Die Frage war nicht wo, sondern wie. Der Slave hat naemlich keinen
Shift-Clock. Der Shift-clock kommt vom Master. Und wie kommt er vom
Master ? Indem der master ein dummy byte sendet.
Oktav Oschi schrieb:> Der Shift-clock kommt vom Master
Ja, so ist SPI nun mal, deswegen heißt der Master ja auch Master. Wenn
der SPI-Slave beim Atmega32 nicht so rudimentär implementiert wäre, wie
A. K. (prx) es beschrieben hat, wäre das kein Problem.
MfG Klaus
Oktav Oschi schrieb:> War die Antwort auf die Bemerkung, dass beim SPI, die Antwort erst auf> das zweite Senden kommt. - worauf denn sonst.
Grundsätzlich kann ein SPI-Slave eine Standardantwort wie etwa
Statusbits bereits zusammen mit dem ersten empfangenen Byte zurück
senden. Also nicht erst als Reaktion auf den Inhalt des Bytes.
So verhält sich beispielsweise das Funkmodul RFM12.
@ Mike (Gast)
>ich beabsichtige zwei Atmega32 miteinander zu verbinden. Ein Atmega>arbeitet zentrale Prozesse ab und koorinidert den Datentransfer.> Der>zweite Atmega soll nur mit einer Unteraufgabe betraut werden, die recht>viele Rechenzyklen frisst.
Da sollte man zuerst mal die Frage stellen, ob man das nicht sinnvoller
auf einem AVR macht. Den der hat ziemmlich viel Rechenpower. Und mit der
richtigen Programmierung mit Interrupt und Multitasking bekommt
man auch knifflige Sachen ind den Griff.
Nur wenn es WIRKLICH nicht reicht sollte man über die Aufteileung auf
zwei oder mehr CPUs nachdenken, denn die Kommunikation zwischen beiden
gibt es nicht geschenkt und ist ggf. aufwändiger oder fehleranfällifer
als eine vollintegrierte Lösung mit einer CPU.
Ergo. Lies was über
http://www.mikrocontroller.net/articles/Netiquette#Klare_Beschreibung_des_Problems
und nenn ein paar mehr Zahlen und Informationen.
MFG
Falk
Hallo,
vielen Dank für die zahlreichen Antworten. Das der SPI-Bus nicht leicht
zu implementieren ist, habe ich gemerkt. Die recht rudimentären
Erklärungen im zugehörigen Datenblatt weisen auf weitergehende
Timingprobleme kaum hin. Eine Anbindung von Peripherie konnte von mir
bereits mehrfach erfolgreich durchgeführt werden (DACs, ADCs etc.), die
Verbindung zwischen uCs hingegen gestaltet sich schwierig.
@Falk
Es geht mir weniger um ein konkretes Problem, als um die Überlegung,
welche Möglichkeit nach eurer Meinung die stabilste und einfachste ist,
um zwei Atmegas miteinander in Beziehung zu setzen. Das klingt nach
"Rundumschlagprobleme als Aufgaben stellen", aber es geht mir um die
generelle Abschätzung, da sich mehrere Möglichkeiten bieten und bislang
keine wirklich befriedigend oder universell erscheint
Mit UART konnte ich bislang die besten Ergebnisse erzielen. SPI bietet
sich hingegen an, wenn ich mehrere Slaves direkt ansprechen möchte.
Somit lag mein Augenmerk zunächst auf dem SPI-Bus. Eine parallele
Implementation würde ich gerne vermeiden, da ich nicht alles in Software
implementieren und nicht pollen möchte. Ausserdem brauche die Ports.
Zu den Timingproblemen:
Meine Untersuchungen des SPI-Bus zeigten, dass zwar die Austaktung des
SPI-Signals sauber erfolgte, der Slave jedoch die gesendeten Daten nicht
immer aus dem Empfangsbuffer holen kann.
@A. K.
Du sagtest, dass der Slave auf das Transmit-Register nur bei inaktivem
SPI-Bus zugreifen kann (CS auf high als Lock?). Kannst du das nochmal
ausführen? Vielleicht habe ich hier schon einen grundlegenden
Denkfehler. Gibt es eine Timingvorschrift, die vom Master eingehalten
werden muss, damit der Slave die Daten auslesen kann? Bislang hatte ich
den Bus so konzipiert, dass immer Einzelbytes gesendet werden und der
SS-Pin des Slves während dieses Bytes auf low gezogen wird. Ein
anschließendes high sollte die SPI-Logik des Slave resetten und den
Interrupt auslösen. So geht das in Praxis aber nicht sauber. Ein
Feedback als Handshake habe ich bislang nicht implementiert. Wenn ich
ein solches einbaue, muss ich da etwas am Timing beachten:
Mit Gruss
Mike
Mike schrieb:> Du sagtest, dass der Slave auf das Transmit-Register nur bei inaktivem> SPI-Bus zugreifen kann (CS auf high als Lock?).
Seiten Ref. Mega32:
S.133: "The system is single buffered in the transmit direction and
double buffered in the receive direction. This means that bytes to be
transmitted cannot be written to the SPI Data Register before the entire
shift cycle is completed.".
S.138: "The WCOL bit is set if the SPI Data Register (SPDR) is written
during a data transfer. The WCOL bit (and the SPIF bit) are cleared by
first reading the SPI Status Register with WCOL set, and then accessing
the SPI Data Register."
Viel mehr verrät Atmel dazu nicht, implementiert habe ich es
wohlweislich auch nicht. I2C bereitet deutlich weniger Ärger und Code
dafür habe ich.
Meine Interpretation: Du hast die Zeit zwischen dem N*8-ten und dem
N*8+1-ten Bit zur Verfügung, um Daten im SPDR unterzubringen, ohne dass
WCOL anschlägt. Indikator wäre SPIF für den Anfang davon, und wenns zu
spät kam eben WCOL. SS high ist dazu wohl nicht unbedingt nötig.
Was ich ohne Hardware-Handshake wohl machen würde wenn ich zwingend auf
SPI angewiesen wäre, als ungetestete Idee:
Das Datenprotokoll so bauen, dass Bytes vom Master zum Slave und Bytes
vom Slave zum Master eindeutig unterscheidbar sind. Wenn dann der Slave
mal seinen Einsatz verpennt und seine Antwort nicht rechtzeitig ins SPDR
schreibt, dann steht im SPDR noch das vom Master beim vorherigen
Byte-Transfer gesendete Byte drin und er kriegt ebendies wieder zurück.
Das kann er dann ignorieren und den Versuch mit ggf. grösserer Wartezeit
wiederholen.
> Gibt es eine Timingvorschrift, die vom Master eingehalten> werden muss, damit der Slave die Daten auslesen kann?
Das Auslesen seitens des Slaves ist relativ harmlos, denn dafür hat er
dank des Pufferregisters ein ganzes Byte Zeit. Wobei es da natürlich
hilfreich sein kann, wenn die Datenrate nicht viel höher als nötig
betrieben wird.
Die Antworten sind das Problem. Denn da gibt der Master ggf. mit einer
programmierbaren Pause zwischen den einzelnen Bytes vor, wieviel Zeit
der Slave für die Reaktion hat um was ins SPDR reinschreiben zu können
ohne dass dieses vom nächsten Byte wieder blockiert ist. Diese
Vorschrift ergibt sich aus deinem Programm vom Slave und dessen
maximaler Reaktionszeit auf SPIF (z.B. der maximalen Interrupt-Latenz.
Weil ich im anderen SPI-Thread grad drüber gestolpert bin:
Multimaster-SPI wäre natürlich auch eine Variante.
Beide stehen normalerweise auf Slave, mit einem SS-raus und einem
SS-rein über Kreuz. Der Master sendet nur, der Slave empfängt nur. Wer
aktiv wird schaut nach ob SS-rein inaktiv ist, stellt sich auf Master,
aktiviert sein SS-raus, haut die Daten raus vorausgesetzt das Master Bit
steht noch, deaktiviert SS-raus und schaut anschliessend noch einmal
nach ob das Master-Bit noch steht. Wenn nicht, dann kam der Kollege
zwischendurch auf die gleiche Idee und es gab eine Kollision.
Hallo,
@Dirk:
Die Datentransferrate liegt noch etwas an der Dimensionierung des
Slaves. Wie ich aber in der Eroeffnung schrieb, gehe ich bislang von
10-20kBit/s aus. Eine Groesse, die also von allen Busarten gut erreicht
werden kann.
@A. K.
Das macht den SPI-Bus langsam uninteressant:(. Gerade die Moeglichkeit
ohne Adressen Slaves direkt adressieren zu koennen und auch hohe
Transferraten zu erzielen war am SPI interessant. I2C machte mir da
immer Probleme. Fuer einfache Master/Slave-Kommunikation erscheint
langsam der UART als stabilste und einfachste Schnittstelle. Sobald ich
jedoch mehr als einen Slave habe, wirds wieder schwierig.
Hast du zur Inspiration evtl. eine Quelle fuer eine saubere
Implementierung eines SPI-Busses? Die Standardimplementation macht
spaetestens hier schlapp und ist auch nicht Fehlertolerant.
Mit Gruss
Mike