Forum: Mikrocontroller und Digitale Elektronik Methoden um 2 Atmegas miteinander zu verbinden


von Mike (Gast)


Lesenswert?

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

von Edi R. (edi_r)


Lesenswert?

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.

von Andreas (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Klaus (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

> 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.

von Klaus (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Klaus (Gast)


Lesenswert?

Das klingt wirklich suboptimal.

MfG Klaus

von Klaus (Gast)


Lesenswert?

Klaus schrieb:
> Das klingt wirklich suboptimal.
>
> MfG Klaus

War jemand dazwischen: bezieht sich auf SPI-Slave von A. K.

MfG Klaus

von Wilhelm F. (Gast)


Lesenswert?

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.

von Purzel H. (hacky)


Lesenswert?

Ueberleg mal wie denn die Daten beim SPI zurueckkommen...

von Klaus (Gast)


Lesenswert?

Oktav Oschi schrieb:
> Ueberleg mal wie denn die Daten beim SPI zurueckkommen...

Über die MISO Leitung, wie bei ADCs, SD-Karten, ...

MfG Klaus

von Coder (Gast)


Lesenswert?

Ich würde die UART benutzen. Bei einem gescheitem Protokoll kannst Du 
die Anzahl der Leitungen auf 1 reduzieren.

von Purzel H. (hacky)


Lesenswert?

>>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.

von Klaus (Gast)


Lesenswert?

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

von Purzel H. (hacky)


Lesenswert?

War die Antwort auf die Bemerkung, dass beim SPI, die Antwort erst auf 
das zweite Senden kommt. - worauf denn sonst.

von Merlon (Gast)


Lesenswert?

TCP/IP

von (prx) A. K. (prx)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@  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

von Mike (Gast)


Lesenswert?

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

von Dirk (Gast)


Lesenswert?

@Mike

von welchen Daten Transfer Raten sprechen wir bei Deiner Anwendung 
überhaupt?

 KBit Bereich, MBit Bereich ?

Gruß

Dirk

von (prx) A. K. (prx)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Mike (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.