Forum: Mikrocontroller und Digitale Elektronik Synchronisation UART, Mega8 mit PC


von Christoph S. (mixer) Benutzerseite


Lesenswert?

Hallo,

ich möchte einen Mega8 mit einem Linux-PC kommunizieren lassen. Dafür 
würde ich gerne jeweils "Bytepakete" Hin- und Hersenden.
Allerdings müsste ich dem Gegenüber erst mitteilen dass jetzt ein neues 
Paket beginnt - aber wie mache ich das am besten??
Evtl. über einen Frame Error? Kann ich den mit dem PC erzeugen??

MFG Mixer

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Nein, Du solltest vielmehr ein sinnvolles Protokoll definieren. Eines, 
wo Pakete mit einem definierten Header beginnen, der unter anderem die 
Anzahl der zum Paket gehörenden Nutzbytes und eine Prüfsumme enthält.

von gast (Gast)


Lesenswert?

Was sind den "Bytepakete" ??
Mit der Standart UART kannst du normalerweiße immer Byteweise senden.
Warum mußt du erst mitteilen das ein neues Pakte kommt?
Der ATmega kann das Byte enpfangen und gibt dir dann einen Interupt das 
ein neues Byte empfangen worden ist. Einfacher geht's wohl kaum.

von Christoph S. (mixer) Benutzerseite


Lesenswert?

Der Mega8 soll aber auch wissen was er mit dem Byte machen soll.
Rufus, ich habe mir schon so etwas in die Richtung gedacht (so ähnlich 
wie bei DMX-512)
Aber wie kann ich dann dem Mega8 mitteilen dass jetzt "Start" ist und 
dann "Ende"??

Steh glaub irgendwie auf m Schlauch...

MFG Mixer

von Karl H. (kbuchegg)


Lesenswert?

Mixer S. schrieb:
> Der Mega8 soll aber auch wissen was er mit dem Byte machen soll.
> Rufus, ich habe mir schon so etwas in die Richtung gedacht (so ähnlich
> wie bei DMX-512)
> Aber wie kann ich dann dem Mega8 mitteilen dass jetzt "Start" ist und
> dann "Ende"??

Tja. Da musst du dir etwas suchen, was in deinen Daten per Definition 
nicht vorkommen kann.
Wenn deine Bytepakete grundsätzlich alle mit einem Byte überhaupt 
möglichen Werte enthalten können, hast du natürlich ein Problem.

Was willst du denn übertragen?

von Christoph S. (mixer) Benutzerseite


Lesenswert?

Eigentlich alles Mögliche, z.B. Werte für Hardware-PWMs, usw. Also es 
können alle Möglichkeiten von $00 bis $FF vorkommen!

Wenn ich die Länge eines Paketes definiere und der Mega8 die empfangenen 
Bytes mitzählt würde das zwar gehen - aber wenn er mal ein Byte vergisst 
würde ja alles durcheinanderkommen!!

MFG Mixer

von Karl H. (kbuchegg)


Lesenswert?

Mixer S. schrieb:
> Eigentlich alles Mögliche, z.B. Werte für Hardware-PWMs, usw. Also es
> können alle Möglichkeiten von $00 bis $FF vorkommen!
>
> Wenn ich die Länge eines Paketes definiere und der Mega8 die empfangenen
> Bytes mitzählt würde das zwar gehen - aber wenn er mal ein Byte vergisst
> würde ja alles durcheinanderkommen!!

Ebent.
Darum kommt es auch auf die jeweilige Anwendung an.

Wenn alle Stricke reissen, kann man zb sowas machen:
Man definiert, dass in den Daten auf der Übertragungsstrecke keine 0xFF 
vorkommen können, schaufelt sich also diesen Bytewert frei.

Nur was, wenn dann tatsächlich mal ein 0xFF übertragen werden muss. Dann 
baut man sich ein Escape-Byte: Man definiert zb das 0xFE nicht direkt 
beim Empfänger als 0xFE interpretiert wird, sondern dass das 
nachfolgende Byte eine andere Bedeutung besitzt. Zb 0x01 bedeutet 0xFE 
und 0x02 bedeutet 0xFF

Damit hat man sich einen Bytewert freigeschaufelt, der ausschliesslich 
für Synchronisationszwecke dient: 0xFF bedeutet 'hier beginnt der 
nächste Datenframe'

(anstelle von 0xFF nimmt man natürlich einen Bytewert von dem man 
erwartet, dass er nicht allzuoft vorkommt)

Wenn dein Protokoll also so aussieht
  0xFF
  1 Byte Länge des Pakets
  Datenbytes (wobei obige Ersetzung zum Tragen kommt)

und deine zu übertragenden Daten wären 0x80 0x40 0x32

Dann würde das Paket auf der seriellen so aussehen

   0xFF 0x03 0x80 0x40 0x32

durch das 0xFF kann sich der Empfänger sauber auf den Start des Pakets 
synchronisieren. Erst dann, wenn er ein 0xFF sieht ist er sicher, dass 
er den Paketanfang gefunden hat

Sind deine Daten 0x80 0xFF 0x20 0xFE 0x32

Dann sieht das Paket zb so aus

  0xFF 0x07 0x80 0xFE 0x02 0x20 0xFE 0x01 0x32

Ob du als Längenangabe die ursprüngliche Länge nimmst oder die Länge die 
sich durch die 0xFF Substitution ergeben hat, bleibt dir überlassen. Ich 
würde die ursprüngliche Länge nehmen, weil dann der Aufrufer der 
Sendefunktion nicht darauf achten muss, dass ein Paket kürzer als 255 
bytes sein muss, wenn es 0xFF Bytes enthält. Auf der anderen Seite mag 
es für jemandem der an der Seriellen mitlauscht befremdlich sein, wenn 
die Längenangabe nicht zu der Anzahl der tatsächlich übertragenen 
Datenbytes passt.   -> Du entscheidest


Edit:
******
Wichtig: Diese Bytewertesubstitution soll so tief wie möglich im 
Kommunikationsstack passieren. Für darüberliegende Schichten soll das 
völlig transparent sein.
Und: Man berücksichtige auch den Fall, dass die Längenangabe einer 
dieser 'verbotenen Werte' sein kann.

von Christoph S. (mixer) Benutzerseite


Lesenswert?

Danke,

glaub so kann ich das mal probieren!!

von holger (Gast)


Lesenswert?

Wenn es nicht auf Geschwindigkeit ankommt übertrage deine
Daten als ASCII Codes. 0xFF einfach zweimal 'F' senden z.B.
Dann können deine Daten nur Codes von '0'-'9' und 'A'-'F'
enthalten. Alle anderen Zeichen kannst du für eine Startkennung
nehmen, z.B. '~' oder '$'. Die Zeichen werden wohl nicht so
häufig benutzt. Ansonsten: Lass dir was einfallen!

von Karl H. (kbuchegg)


Lesenswert?

gast schrieb:

> Einfacher geht's wohl kaum.

Sowas kann nur jemand sagen, der sich noch nie Gedanken über eine 
robuste Kommunikation gemacht hat :-)

Zu deiner Info:
Robuste Kommunikation bedeutet auch, dass man zwischendurch einfach den 
RS232 Stecker abziehen, wieder aufstecken kann und alles läuft weiter 
wie gewohnt (abzüglich der fehlenden Daten natürlich). Sprich: Sender 
und Empfänger synchronisieren sich wieder selbsttätig.

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Eine weitere einfache Möglichkeit ist die Implementierung eines 
Protokolls per endlicher Zustandsmaschine. Dann entfällt auch das ganze 
Escaping.

von gast (Gast)


Lesenswert?

>Sowas kann nur jemand sagen, der sich noch nie Gedanken über eine
>robuste Kommunikation gemacht hat :-)
>Zu deiner Info:
>...

danke für die Info.
Von robuster Kommunikation war aber nicht die rede.
und das nicht nur "Bytepaket" übertragen werden soll sondern auch noch 
Steuerinfos wurde erst später erwähnt. Und das es da einen Stecker gibt 
auch nicht.

von Christoph S. (mixer) Benutzerseite


Lesenswert?

> Von robuster Kommunikation war aber nicht die rede.
> und das nicht nur "Bytepaket" übertragen werden soll sondern auch noch
> Steuerinfos wurde erst später erwähnt. Und das es da einen Stecker gibt
> auch nicht.

Stecker gibts! Genauso wie Stromausfälle auf beiden Seiten, unerwartete 
Abstürze des Betriebssystems auf PC-Seite und unerwartete Reset's auf 
µC-Seite...
Das hab ich eig. als selbstverständlich angesehen...

Werd aber trotzdem zuerst mal den Ansatz von Karl Heinz ausprobieren, 
weil es für mich sehr verständlich und einfach klingt. Außerdem hat er 
auch viel Mühe beim Beschreiben gegeben!

MFG Mixer

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dem von Karl Heinz beschriebenen Paket würde ich auf jeden Fall noch 
eine Prüfsumme mitgeben. Nach dem Empfang der durch die 
Paketlängenangabe definierten Anzahl an Daten wird die Prüfsumme der 
empfangenen Daten bestimmt und mit der aus dem Paketheader verglichen.
Dann ist auch ein "Escaping" nicht nötig, weil so auch zufälliges 
Auftreten der Paketanfangskennung erkannt werden kann: Die Prüfsumme 
stimmt nicht.

Wird zusätzlich eine Prüfsumme über den Paketheader definiert, so kann 
bereits nach Empfang des Headers herausgefunden werden, ob der gültig 
ist, und der Paketanfangserkennungsvorgang neu gestartet werden.

Mit zusätzlichen logischen Einschränkungen kann auch die Paketgültigkeit 
verifziert werden, bsp. könnte die Paketlängenangabe zwar ein 
16-Bit-Wert sein, aber nie größer als 4096 werden ... oder was halt 
sinnvoll im Rahmen des geforderten Protokolles ist.

von P. S. (Gast)


Lesenswert?

Ralf Schwarz schrieb:
> Eine weitere einfache Möglichkeit ist die Implementierung eines
> Protokolls per endlicher Zustandsmaschine. Dann entfällt auch das ganze
> Escaping.

Wie das?

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Für Rufus' Protokoll könnte das empfängerseitig so ähnlich wie folgt 
aussehen:


 -----------   <-----------,
|   START   |      ^ (5)   |
 -----------   ----´       |
      |                    | (7)
      | (1)                |
      v                    |
 -----------        (8)    |
| PRÄAMBEL  |  <-----------|
 -----------               |
      |                    |
      | (2)                |
      v                    |
 -----------               |
|   LÄNGE   |              |
 -----------               |
      |                    |
      | (3)                |
      v                    |
 -----------   <---,       |
|   DATEN   |      | (6)   |
 -----------   ----´       |
      |                    |
      | (4)                |
      v                    |
 -----------               |
| PRÜFSUMME |  ------------'
 -----------


Die Übergänge würden dann wie folgt ausgelöst:

  (1) Präambel empfangen
  (2) Byte empfangen (Länge)
  (3) Byte empfangen (Datum)
  (4) Byte empfangen (Prüfsumme)
  (5) Byte empfangen, aber nicht Präambel
  (6) Byte empfangen, weitere Daten kommen noch
  (7) Byte empfangen (nicht Präambel)
        Falls Prüfsumme okay -> Daten weiterverarbeiten
  (8) Präambel empfangen
        Falls Prüfsumme okay -> Daten weiterverarbeiten

So ziemlich alle hier nicht eingezeichneten Übergänge müssten noch durch 
ein Timeout ausgelöst werden, damit das zuverlässig funktioniert.

Das ist natürlich nicht unbedingt die effizienteste Lösung. Aber wenn 
man das Protokoll mal noch erweitern oder umbauen will, hat man nicht so 
einen grossen Aufwand.

von P. S. (Gast)


Lesenswert?

Nur laesst deine Implementierung einfach die Anforderung des eindeutigen 
Startcodes weg. Die Statemachine vollbringt also kein Wunder, sondern 
ist nur eine huebsche Darstellung eines Parsers fuer ein vereinfachtes 
Protokoll.

von Karl H. (kbuchegg)


Lesenswert?

Rufus t. Firefly schrieb:

> Dann ist auch ein "Escaping" nicht nötig, weil so auch zufälliges
> Auftreten der Paketanfangskennung erkannt werden kann: Die Prüfsumme
> stimmt nicht.

Damit bist du aber immer noch nicht aus dem Dilemma heraus, dass du ein 
zufälliges Auftreten des Startbytes im weiteren Datenstrom als nächsten 
Paketanfang interpretierst. Du fängst dort wieder zu lesen an und auch 
diese Prüfsumme wird nicht stimmen etc. Das geht solange bis ein Paket 
übertragen wird, in dem das Startbyte nach der 'falschen 
Prüfsummenposition' nicht mehr auftritt. Erst dann synchronisieren sich 
Sender und Empfänger wieder.

> Wird zusätzlich eine Prüfsumme über den Paketheader definiert, so kann
> bereits nach Empfang des Headers herausgefunden werden, ob der gültig
> ist, und der Paketanfangserkennungsvorgang neu gestartet werden.

Das wäre allerdings eine Lösung um zu entscheiden ob ein Startwert 
tatsächlich das Startbyte war oder nicht.

Möglichkeiten gibt es viele.
Mit dem Escaping ist es wasserdicht, darum hab ich diesen Vorschlag 
gemacht.

von Karl H. (kbuchegg)


Lesenswert?

Ralf Schwarz schrieb:

> So ziemlich alle hier nicht eingezeichneten Übergänge müssten noch durch
> ein Timeout ausgelöst werden, damit das zuverlässig funktioniert.

Was wenn dein Datenstrom einfach kein Timeout zulässt?

Ausserdem rettet dich dein Verfahren immer noch nicht davon, dass du 
einem falschen Startbyte mitten im Datenstrom aufsitzt und ständig das 
Paket falsch auswertest.

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Peter Stegemann schrieb:
> Nur laesst deine Implementierung einfach die Anforderung des eindeutigen
> Startcodes weg.

Ja sorry, bei mir heisst das einfach "Präambel".

> Die Statemachine vollbringt also kein Wunder, sondern
> ist nur eine huebsche Darstellung eines Parsers fuer ein vereinfachtes
> Protokoll.

Nee, das vollbringt sie noch nicht. War mir aber auch nicht bewusst, 
dass das die Anforderung ist in diesem Projekt.

von Karl H. (kbuchegg)


Lesenswert?

gast schrieb:
>>Sowas kann nur jemand sagen, der sich noch nie Gedanken über eine
>>robuste Kommunikation gemacht hat :-)
>>Zu deiner Info:
>>...
>
> danke für die Info.
> Von robuster Kommunikation war aber nicht die rede.
> und das nicht nur "Bytepaket" übertragen werden soll sondern auch noch
> Steuerinfos wurde erst später erwähnt.

1) Dürfte das ziemlich klar sein. Ein Paket existiert ja nicht im 
luftleeren Raum. Die Daten stellen irgendetwas dar und in den seltensten 
Fällen hat man nur einen Strom von Bytes, in dem jedes einzelne Byte 
tatsächlich einen Wert darstellt.
2) Was machen wir hier?
Machen wir Bastelprogramme oder wollen wir was Vernünftiges?

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

> Ausserdem rettet dich dein Verfahren immer noch nicht davon, dass du
> einem falschen Startbyte mitten im Datenstrom aufsitzt und ständig das
> Paket falsch auswertest.

Dazu dient ja die Checksumme.

von Karl H. (kbuchegg)


Lesenswert?

Ralf Schwarz schrieb:
> Peter Stegemann schrieb:
>> Nur laesst deine Implementierung einfach die Anforderung des eindeutigen
>> Startcodes weg.
>
> Ja sorry, bei mir heisst das einfach "Präambel".
>
>> Die Statemachine vollbringt also kein Wunder, sondern
>> ist nur eine huebsche Darstellung eines Parsers fuer ein vereinfachtes
>> Protokoll.
>
> Nee, das vollbringt sie noch nicht. War mir aber auch nicht bewusst,
> dass das die Anforderung ist in diesem Projekt.

Ist ja kein Problem.
Deine Auswertung ist einfach nur auf einer anderen Schichtebene 
anzusiedeln. Unterste Schicht ist es, ein Paket völlig ohne jegliche 
Möglichkeit für Fehler zu übertragen. Sender und Empfänger müssen sich 
selbst soweit synchronisieren, dass der Empfänger ohne jeden Zweifel ein 
Paket aus dem Datenstrom herausfischen kann.
Und zu guter letzt soll natürlich diese Synchronisierung möglichst rasch 
erfolgen, damit nicht zuviele Daten verloren gehen.

von Andy H. (vinculum) Benutzerseite


Lesenswert?

10 02 = STX Start of text
10 03 = ETX end of text

wenn im Datensatz eine 10 vorkommt, wird eine weitere 10 eingefügt

z.B.

10 02 01 02 10 10 04 05 10 03

ergibt

01 02 10 04 05

ergänzt in der Regel durch eine angehängte Prüfsumme

so habe ich es in Nachrichtentechnik gelernt

von Karl H. (kbuchegg)


Lesenswert?

Ralf Schwarz schrieb:
>> Ausserdem rettet dich dein Verfahren immer noch nicht davon, dass du
>> einem falschen Startbyte mitten im Datenstrom aufsitzt und ständig das
>> Paket falsch auswertest.
>
> Dazu dient ja die Checksumme.

Ja. ok.
Damit stellst du fest, dass die letzten Bytes kein Paket gebildet haben.
Und, wie geht es weiter?
Du liest weiter. Da du aber die Paketgrenze falsch angenommen hast, 
triggert das nächste Datenbyte mit dem richtigen Wert den nächsten 
Auswerteversuch. Und schon liest du schon wieder Bytes zu einem Paket 
zusammen die eigentlich nicht zusammengehören. Klarerweise wird die 
Checksumme dann wieder nicht stimmen, woraufhin du das Paket verwirfst 
und im Datenstrom nach dem nächsten Startbyte suchst. Wenn das 
blöderweise wieder mitten in den Daten auftaucht, versucht deine 
Statemachine das nächste mal erfolglos sich auf eine falsche Paketgrenze 
zu synchronisieren.

Wenn die Datenbytes richtig stehen, kann dieses Spielchen noch 
stundenlang so weitergehen, ohne dass sich deine Statemachine wieder 
korrekt in den Datenstrom einlockt.

von (prx) A. K. (prx)


Lesenswert?

Karl heinz Buchegger schrieb:

> Mit dem Escaping ist es wasserdicht, darum hab ich diesen Vorschlag
> gemacht.

Nicht ganz, dafür sorgt die asynchrone Kommunikation. Wenn nonstop Daten 
gesendet werden kann es vorkommen, dass der Empfänger nie auf's Byte 
synchronisiert weil er nie weiss wo eines anfängt.

Drum: Vor jedem Paket bischen Pause lassen, entsprechend >1 Byte.

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> Karl heinz Buchegger schrieb:
>
>> Mit dem Escaping ist es wasserdicht, darum hab ich diesen Vorschlag
>> gemacht.
>
> Nicht ganz, dafür sorgt die asynchrone Kommunikation. Wenn nonstop Daten
> gesendet werden kann es vorkommen, dass der Empfänger nie auf's Byte
> synchronisiert weil er nie weiss wo eines anfängt.

I stand corrected :-)
Da hast du natürlich recht.

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

> Wenn die Datenbytes richtig stehen, kann dieses Spielchen noch
> stundenlang so weitergehen, ohne dass sich deine Statemachine wieder
> korrekt in den Datenstrom einlockt.

Ja, das stimmt natürlich. Aber meiner Meinung nach ist dein Einwand ein 
etwas akademischer Fall. Mit realen Daten wird sich der Empfänger mit 
sehr hoher Wahrscheinlichkeit einsynchronisieren. Und falls der 
Datenstrom nicht kontinuierlich ist, kann man via Timeout wieder in den 
Anfangszustand kommen.

von Karl H. (kbuchegg)


Lesenswert?

Ralf Schwarz schrieb:
>> Wenn die Datenbytes richtig stehen, kann dieses Spielchen noch
>> stundenlang so weitergehen, ohne dass sich deine Statemachine wieder
>> korrekt in den Datenstrom einlockt.
>
> Ja, das stimmt natürlich. Aber meiner Meinung nach ist dein Einwand ein
> etwas akademischer Fall.

Mag sein.
Deshalb habe ich am Anfang nach den Daten selbst gefragt.

Kommt halt immer darauf an, wie allgemein so etwas verwendbar sein soll. 
Wenn ich eine sichere Paketverbindung als Plug&Play Baustein haben 
möchte, würde ich auf jeden Fall zu escaping greifen, wenn sich nichts 
Eindeutiges als Startbyte anbietet.

> Datenstrom nicht kontinuierlich ist, kann man via Timeout wieder in den
> Anfangszustand kommen.

dazu muss ich allerdings auch sagen, dass ich Timeout als Mittel zur 
Kommunikationssteuerung nicht sehr gerne verwende. Das Schreckgespenst 
eines Timeout durch herunterfallendes Kabel steht da bei mir immer im 
Raum. Und das von einem gewollten Timeout von der Sendeseite zu 
unterscheiden ist praktisch nicht möglich.

von (prx) A. K. (prx)


Lesenswert?

NB: Was KHB hier beschrieben hat ist letztlich nichts anderes als das 
Verfahren im asynchronen PPP, wie man es im Internet-Anschluss mit 
Modems verwendet hat. Funktionierte da eigentlich ganz gut.

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.