Forum: Mikrocontroller und Digitale Elektronik Serielle Daten entknüpfen


von Ingo (Gast)


Lesenswert?

Hallo zusammen,

da ich auf keine grünen Zweig komme, möchte mal fragen wie ihr so etwas 
machen würdet:
Aufbau: Ein 90S2313 sendet über UART fünf Bytes im Sekundentakt, ein 
zweiter 90S2313 empfängt diese. So weit so gut.
Diese fünf Bytes bedeuten
1.byte = Startbyte
2.byte = Temperatur
3.byte = Anlagenstatus
4.byte = ist immer null
5.byte = ist immer 255

Der Empfang funktioniert. Nun möchte ich das 3.Byte auswerten.
Nun kann es aber sein, das der Empfänger gerade dann eingeschaltet wird, 
wenn der Sender gerade schon sendet (also das die ersten bytes schon 
abgeschickt sind). Wie kann man nun die
Empfangenen Bytes daraufhin überprüfen, das Byte3 auch wirklich byte3 
ist und nicht irtümlich Byte4 als Anlagenstatus ausgewertet wird? 
Danke für jeden Tip!

von Christian Schifferle (Gast)


Lesenswert?

Ganz einfach.
Du hast ja ein Startbyte! Mit diesem kannst (musst) du synchronisieren, 
d.h. wenn du das Startbyte empfängst setzt du einen Zähler auf 0 und 
zählst dann die eintreffenden Bytes.
Du musst aber dafür sorgen, dass die folgenden Bytes niemals den Wert 
des Startbytes annehmen können, z.B. indem du beim Sender einen Offset 
addierst, welchen du dann beim Empfänger wieder subtrahierst.
Als Startbyte verwendet man üblicherweise Hex 0x02, welches auch als STX 
bezeichnet wird.
Falls du es ganz genau machen willst kannst du am Ende des Telegramms 
noch ein Hex 0x03 (ETX) anhängen.

Gruss
Christian

von crazy horse (Gast)


Lesenswert?

so isses, immer schöne frames bilden. und statt 00 und 0xff würde ich 
lieber ein Prüfsummenbyte schicken, so hat der Empfänger die 
Möglichkeit, Übertragungsfehler zu erkennen.
Solltest du Probleme haben, das Startbyte eindeutig zu haben (weil die 
Datenbytes denselben Wert annehmen können) wandle die Datenbytes in 2 
Hex-Ascii-Bytes um.
Bsp: zu sendendes Datum 0x28, sendest du 0x32 (ASCII '2'), 0x38 (ASCII 
'8'). Mit diesem Verfahren hast du den ganzen Bereich unter 0x30 für 
eindeutige Steuerzeichen zur Verfügung.

von Ingo (Gast)


Lesenswert?

Einfach genial! Ich glaub' ich nehme beide Tips und vereinige sie im 
Prog.
Dankeschön!

von Peter D. (peda)


Lesenswert?

Wenn die Daten nur jede 1s kommen, kann man auch einen Timer aufsetzen. 
Dann muß man nur die 2 Datenbytes senden:

Wenn ein Byte empfangen wird, wird ein Timer gestartet. Wird dann das 
2.Byte nicht innerhalb von 10ms empfangen, dann war das ein Fehler. 
Ansonsten hat man die 2 Bytes und wertet sie aus.´

Das ist eine sehr einfache und gebräuchliche Methode.
Wichtig ist eben nur, daß die minimale Zeit zwischen 2 Paketen immer 
länger ist, als die maximale Zeit zwischen 2 Bytes eines Pakets.


Peter

von crazy horse (Gast)


Lesenswert?

sicher, das geht, aber gebräuchlich würde ich das nicht nennen. Solche 
Sachen sind immer empfindlich gegen nachträgliche Änderungen, wer weiß 
schon, was alles noch kommt. Irgendwann wird die Übertragungsrate erhöht 
(50x/s), weitere Daten kommen hinzu,die Baudrate muß erniedrigt werden 
(lange Strecke) usw. Saubere Frames basteln ist meiner Meinung nach 
immer die bessere Lösung.

von edi (Gast)


Lesenswert?

hi,

die methode von peter d. benuetze ich auch.ist vollkommen angemessen 
fuer diesen fall. wenig software ....und wer braucht schon einen traegen 
temperaturwert 50x /sekunde?
lange leitungen,niedrige baudrate ...wo gibt es da probleme?

stx , etx  und womoeglich bcc sind in diesem fall uebertrieben.

..aber: jedem tierchen sein plaesierchen.

ciao

von Peter D. (peda)


Lesenswert?

Zum Thema "Saubere Frames":

Wenn man spezielle Steuerbytes definiert, dürfen diese dann aber auch 
nie in den Daten enthalten sein !

Deshalb wird STX, ETX, CR, LF, usw. nur bei Textübertragung benutzt, 
d.h. wenn die Datenbytes immer >=20h sind.

Müssen echte Binärdaten übertragen werden, wird das schon komplizierter.


Peter

von crazy horse (Gast)


Lesenswert?

Korrekt.
Zum Thema Steuerzeichen: siehe oben
Ist wirklich eine Binärübertragung nötig (hat letzlich die höchste 
Nutzdatenrate) benutze ich die 9bit-Übertragung (Steuerbytes aller Art 
mit TB8=1, Nutzdaten TB8=0)
Ich will hier keinen Glaubenskrieg entfachen, alles hat seine  Vor- und 
Nachteile.
Aber die Sache mit der Zeitsynchronisierung KANN anfällig werden, und 
mit meiner bevorzugten Methode spare ich mir, über solche Sachen 
überhaupt nachdenken zu müssen. Die Routinen dafür sind fertig, warum 
also soll man sich solche Hilfskrücken antun?
mfg crazy horse

von Manfred Glahe (Gast)


Lesenswert?

Hallo,
um ganz sicher zu sein ob die empfangenen Daten auch mit den gesendeten 
übereinstimmen reicht ein Parity oder auch eine Prüfsumme nicht aus. 
Mehrfachfehler in beiden Byt's werden nicht erkannt.
Für fehlerfreie Steuerdaten übertrage ich einen Block 3 mal und 
vergleiche die im Empfänger. Das alle drei falsch sind und trotzdem 
übereinstimmen ist noch nie vorgekommen.
MfG  Manfred Glahe

von Oliver K. (Gast)


Lesenswert?

Quatsch, alles viel zu kompliziert und eingeschränkt!
Daten werden sauber in ein Frame gepackt:
"DLE STX Daten DLE ETX"
Kommt in den Daten ein DLE vor, wird es verdoppelt.
Ausgelesen und ausgewertet wird ein solcher Frame durch einen Automaten:


sercom_tlg_len: Telegrammbyte-Zaehler
EmpfangenesTlg[]: Telegrammpuffer
recByte: Empfangenes Byte von der Schnittstelle

Initialisierung: state_receive = 0;


// Dieser Automat wird jedes Mal beim Empfang eines Zeichens aufgerufen
switch (state_receive)
{
case 0: if (recByte == DLE) state_receive = 1;  break;
case 1:  if (recByte == STX)
  {state_receive = 2; sercom_tlg_len = 0;}
  else if (recByte != DLE) state_receive = 0;
  break;

case 2:  EmpfangenesTlg[sercom_tlg_len++] = recByte;
  if (DLE == recByte) state_receive = 3;
  break;

case 3: if (recByte == DLE)
  {
  state_receive = 2;
  }
  else if (recByte == ETX)
  {
  // Ende-DLE wieder entfernen
  sercom_tlg_len--;

  // Telegrammdaten koennen ausgewertet werden
  //...

  state_receive = 0;
  }
  break;

default: state_receive = 0; break;
}

von Weinga-Unity (Gast)


Lesenswert?

Hi!

Ich verwende im folgendes Prinzip bei solchen Sachen:

Ich empfange ein Byte, und schiebe es in ein Byte-Schiebe-Register, das 
in diesen Fall 5 Bytes lang wäre.

Dann schau ich immer bei jedem Empfang nach, ob Die Bytes wie Start und 
Stop-Bytes korrekt sind. Bei dem Beispiel wären es das Byte 1, 4 und 5. 
Und wenn das der Fall ist, dann kannst du ja das Byte 2, und 3 exakt 
auslesen.

mfg Weinga-Unity

von Jens Gerdes (Gast)


Lesenswert?

Richtig, Oliver K. Das ist die Lösung, die ich seit Jahren in 
professionellen Produkten einsetze (mit 16bit CRC hinten dran). Bei so 
einem Frame erkent man das Ende, egal wann man in die Übertragung 
einsteigt.

von Oliver K. (Gast)


Lesenswert?

Ich danke Dir Jens!

Grüße
Oliver

von Peter D. (peda)


Lesenswert?

Die Methode mit dem Timeout hat den riesen Vorteil, daß, wenn jemand 
übers Kabel stolpert und es dann wieder reinsteckt, der Timeout sofort 
zuschlägt und die Gefahr erkannt und gebannt hat.

Bei einer Frame-Statemaschine dagegen, kann diese für immer 
hängenbleiben oder ein halbes altes Paket mit einem halben neuen 
fehlerhaft zusammenbasteln.


Für absolut maximale Geschwindigkeit sendet man die Bytes im 
TX-Interrupt mit höchster Priorität (PS = 1) direkt hintereinander und 
wartet immer eine Bytezeit zum nächsten Paket (160*Timer T1 Überlauf).

Der Empfänger zählt dann auch die T1-Überläufe und erkennt irgendwo 
zwischen 160 < x < 320 (z.B. bei 255) das Ende eines Pakets.

Lange, kurze oder variable Pakete und Änderung der Baudrate haben da 
überhaupt keinen Einfluß.


Ob man bei langen Paketen und langen Leitungen auch noch eine CRC mit 
ins Paket aufnimmt oder andere Fehlererkennungsmethoden, ist eine ganz 
andere Sache.

Denke mal, daß Ingo vorerst auf sowas verzichten kann.
Wenns erstmal läuft, kann man sowas ja immer noch einfügen.


Peter


P.S.: PS und T1 beziehen sich auf eine 8051-Architektur.

von Oliver K. (Gast)


Lesenswert?

> Bei einer Frame-Statemaschine dagegen, kann diese für immer hängenbleiben oder 
ein halbes altes Paket mit einem halben neuen fehlerhaft zusammenbasteln.

Nein. Sie bleibt nicht hängen. Lediglich auf einen Pufferüberlauf muß 
man achten, falls ein Telegramm abgeschnitten wird und ein neues (als 
ein nicht neu erkanntes Telegramm) den Puffer weiter füllt.
Das Erkennen, ob ein gültiges Telegramm empfangen wurde, wird in der 
Auswertung der Daten vorgenommen. Wie schon Jens schrieb, ist ein 16-Bit 
CRC eine gute Lösung.

Grüße
Oliver

von Oliver K. (Gast)


Lesenswert?

Ups! Beim kopieren der Routine ist mir ein Fehler passiert.

Case 3 muß so sein:(//!!!!!!!)

Damit kann sich der Automat bei einem Fehler wieder synchronisieren.

case 3: if (recByte == DLE)
  {
  state_receive = 2;
  }
  else if (recByte == ETX)
  {
  // Ende-DLE wieder entfernen
  sercom_tlg_len--;

  // Telegrammdaten koennen ausgewertet werden
  //...

  state_receive = 0;
  } else state_receive = 0; //!!!!!!!!!!
  break;

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.