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: > Das klingt wirklich suboptimal. > > MfG Klaus War jemand dazwischen: bezieht sich auf SPI-Slave von A. K. MfG Klaus
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.
Ueberleg mal wie denn die Daten beim SPI zurueckkommen...
Oktav Oschi schrieb: > Ueberleg mal wie denn die Daten beim SPI zurueckkommen... Über die MISO Leitung, wie bei ADCs, SD-Karten, ... MfG Klaus
Ich würde die UART benutzen. Bei einem gescheitem Protokoll kannst Du die Anzahl der Leitungen auf 1 reduzieren.
>>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
War die Antwort auf die Bemerkung, dass beim SPI, die Antwort erst auf das zweite Senden kommt. - worauf denn sonst.
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 von welchen Daten Transfer Raten sprechen wir bei Deiner Anwendung überhaupt? KBit Bereich, MBit Bereich ? Gruß Dirk
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
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.