www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Serielle Daten entknüpfen


Autor: Ingo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Christian Schifferle (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ingo (Gast)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: edi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Manfred Glahe (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Oliver K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

Autor: Weinga-Unity (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jens Gerdes (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Oliver K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich danke Dir Jens!

Grüße
Oliver

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Oliver K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Oliver K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.