Angenommen mir werden von außen Telegramme geschickt. Ungefährer Aufbau wäre sowas: ID (1Byte)| Länge in Byte (1Byte)| Daten (max. 255 Bytes)| CRC (2 Bytes) Wie realisiere ich das im Programmablauf am besten, dass ich weiß ob ein Telegramm vollständig und korrekt empfangen wurde. Beispiel: Ich empfange zwei Bytes, also die ID und die Länge in Byte. Jetzt könnte ich daraus ja folgern "aha, also kommen noch X Datenbytes + die CRC". Allerdings weiß ich ja erst mit der CRC, ob meine empfangenen Daten überhaupt korrekt sind. Versteht ihr was ich meine? Wie kann ich prüfen, ob ich Daten vollständig und korrekt empfangen habe?!
DruckPause schrieb: > Beispiel: > Ich empfange zwei Bytes, also die ID und die Länge in Byte. Jetzt könnte > ich daraus ja folgern Nicht 'könnte'. Das ist alles was du hast! Der Konjunktiv ist da nicht angebracht, denn du hast sowieso keine andere Wahl bei diesem Protokoll. > Wie kann ich prüfen, ob ich Daten vollständig und korrekt empfangen > habe?! Das Telegramm fängt mit der bekannten ID an. Ab dort gelten die Bytes. Wenn dann hinten nach die CRC nicht stimmt, dann läuft dein Empfänger asynchron und hat ein paar Datenbytes mit der ID verwechselt. Deine einzige Hoffnung lautet: überlesen von Bytes, bis die ID wieder auftaucht und dann hoffen, dass das auch wirklich die ID war und du nicht schon wieder auf ein paar Datenbytes mit zufällig genau den richtigen ID-Werten hereingefallen bist.
In dem du wartest bis nach Deiner ID+Byte die Anzahl der Daten kommen. (TimeOut). Sind Deine Daten Byte(Anzahl)+2Byte(CRC) da, rechnest du den CRC zurück und schaust ob er mit den letzten zwei Byte gleich ist ( bzw. 0 )
Es gibt ja verschiedene Telegramm IDs wovon dann die Gesamtlänge abhängt. Im Prinzip löst man das also tatsächlich mit einem Timeout? So wie von Holger P. beschrieben? Holger P. schrieb: > In dem du wartest bis nach Deiner ID+Byte die Anzahl der Daten kommen. > (TimeOut). Sind Deine Daten Byte(Anzahl)+2Byte(CRC) da, rechnest du den > CRC zurück und schaust ob er mit den letzten zwei Byte gleich ist ( bzw. > 0 )
Wenn zwischen den Telegrammen in jedem Fall Pausen bestimmter Länge sind, kann man erstmal auf diese Pausen Syncronisieren. Ein CRC Check des gesamten Pakets ist trotzdem immer angebracht. Dann kann man noch feste Header und Trailer vorsehen auf die man testet. z.B. ein STX an den Anfang und ein ETX ans Ende. Prinzipiell kannst du auch mit Steuerzeichen arbeiten welche durch ein "Escape-Zeichen" von den Daten getrennt werden. Damit kannst du die Steuerzeichen eindeutig von den Daten unterscheiden. http://de.wikipedia.org/wiki/Escape-Sequenz Ist aber IMO meist nicht nötig wenn man die obigen Verfahren einsetzt. gruß cyblord
DruckPause schrieb: > Es gibt ja verschiedene Telegramm IDs wovon dann die Gesamtlänge > abhängt. > > Im Prinzip löst man das also tatsächlich mit einem Timeout? Ein Timeout ist immer die schlechteste Methode für die Synchronisierung. Ein Timeout löst die Fragestellung: Ist die Gegenstelle überhaupt noch da? Stell dir einfach den simplen Fall vor: Aus irgendeinem Grund wird das UART Kabel aus der Buchse gezogen und neu eingesteckt. Ein gutes Protokoll kommt damit klar und synchronisiert sich wieder in den laufenden Datenstrom. Denn: solange nichts unvorhergesehenes passiert ist alles sowieso kein Problem. Interessant sind immer die Fälle, bei denen dann eben doch etwas unvorhergesehenes passiert, wie zb ein Zusammenbruch der Verbindung. Aus welchem Grund auch immer und sei es nur, weil die Putzfrau das Kabel runtergerissen hat.
Karl Heinz Buchegger schrieb: > Ein Timeout ist immer die schlechteste Methode. > > Stell dir einfach den simplen Fall vor: > Aus irgendeinem Grund wird das UART Kabel aus der Buchse gezogen und neu > eingesteckt. > > Ein gutes Protokoll kommt damit klar und synchronisiert sich wieder. > Auch ohne irgendwelche Timeouts. wie soll das den gehen ohne timeouts? Wenn ständig irgendwelche Daten ankommen (wirklich alles 0-255) dann schafft es die client sich nur durch zuffall zu synchen. Meist wartet aber der Host auf eine Antwort, und diese lücke kann der client ausnutzen um sich neu zu synchen (also Timeout). Wie soll das denn ohne timeout und ohne extra startbyte/endbyte denn gehen?
Also ich verwende immer eine Sate-macine in der UART-ISR. Hat sich so bewährt. Startzeichen? (sonst IDLE) Länge => zum füttern der Schleife im Datenempfang Daten .... CRC Stoppzeichen Wenn das Stoppzeichen und die Länge zusammenpasst wirde der Status auf FINISHED gesetzt. In der while(1) wird abgefragt ob der Satus FINISHED ist. Wenn ja wird die CRC berechnet und verglichen. Ein Timeout kommt zum Schutz oben drauf. Beim Empfang des Startzeichens wird ein Timer gestartet und beim Stoppzeichen beendet. Ansonsten springt er in seine ISR und setzt die Statemachine zurück.
Peter II schrieb: > wie soll das den gehen ohne timeouts? Hallo! Du vermischt hier die Bedeutung etwas. Du meinst Lücke im Datenstrom, die der Sender bewußt einfügt. Timeout im Empfänger heißt, es kommen in vorgegebener Zeit keine, oder zu wenig Zeichen an.
Route 66 schrieb: > Hallo! > Du vermischt hier die Bedeutung etwas. Du meinst Lücke im Datenstrom, > die der Sender bewußt einfügt. Timeout im Empfänger heißt, es kommen in > vorgegebener Zeit keine, oder zu wenig Zeichen an. es kann ein timeout auch beim Empfänger geben. In der Art: zwischen 2 zeichen innerhalb des Packets darf maximal eine lücke von 10ms sein. Dann hat der client die Möglichkeit, sich zurückzusetzen und auf das nächste packet zu warten.
Hatte ich nicht geschrieben "Timeout im Empfänger..."? Grübel, Grübel.
Route 66 schrieb: > Hatte ich nicht geschrieben "Timeout im Empfänger..."? > Grübel, Grübel. ja, sorry ab mit was soll ich es dann da vermischen ?
Peter II schrieb: > ja, sorry ab mit was soll ich es dann da vermischen ? Man darf nicht einfach die verschiedenen Lückenarten vermischen: es gibt "gute" Lücken, die immer vorkommen (müssen) und "schlechte" Lücken durch Übertragungfehler, Unterbrechungen etc. Beide muß man beherrschen und unterschiedlich darauf reagieren. Die erste Lücke führt zur normalen Abarbeitung und die zweite zur Fehlerbehandlung. EDIT: Die erste merkt man normalerweise nicht!
Peter II schrieb: > Meist wartet aber der Host auf eine Antwort, und diese lücke kann der > client ausnutzen um sich neu zu synchen (also Timeout). Wie soll das > denn ohne timeout und ohne extra startbyte/endbyte denn gehen? Genau das ist der springende Punkt: Es geht nur mit dezidierten Start/Stopp Bytes, die in den Daten nicht vorkommen. Das ist die sicherste Art und Weise. Da kann dir nichts passieren, auch wenn es durch möglicherweise notwendiges Escapen ein wenig aufwendig ist.
Karl Heinz Buchegger schrieb: > Es geht NUR mit dezidierten Start/Stopp Bytes, die in den Daten nicht > vorkommen. aber das ist doch dann auch nicht Lösung aller Probleme. Damit habe ich dann Probleme wenn ich viele daten effektiv übertragen will. Und die häufigste Anwendung ist doch das ein Host bei client anfragt und auf die Antwort wartet. Wenn der client das Packet nicht verstanden (weil er den anfang nicht mitbekommen hat) dann kann man das Problem geschickt mit einem timeout lösen.
Peter II schrieb: > Wenn der client das Packet nicht verstanden > (weil er den anfang nicht mitbekommen hat) dann kann man das Problem > geschickt mit einem timeout lösen. Du willst also immer einen Fehler provozieren, damit das folgende Paket synchronisiert werden kann? Wie verträgt sich das mit der von dir (unnötigerweise) geforderten Effektivität? Gruss Reinhard
Reinhard Kern schrieb: > Du willst also immer einen Fehler provozieren, damit das folgende Paket > synchronisiert werden kann? Wie verträgt sich das mit der von dir > (unnötigerweise) geforderten Effektivität? was für ein Fehler provozieren? Wenn nur das halbe Packet, wegen einen kabel fehler, nicht bei client ankommt hat nicht mit Fehler provozieren zu tun?
DruckPause schrieb: > Versteht ihr was ich meine? Ja. Du hast eine grundfalschen Denkansatz. Also erstens: Wenn du alle möglichen Bytes 0..255 für alles zuläßt, dann hast du garkeine Möglichkeit zu irgendwelcher Kontrolle, außer solchen Methoden, wie sie z.B. beim RDS Dekodieren angesagt sind, wo also über eine Vielzahl von empfangenen Bits ein bestimmtes Muster gesucht wird zur Synchronisation. Zweitens: Was hier an Vorschlägen kam über Timeouts usw. ist Mumpitz. Schließlich reden wir hier über den Datenverkehr über einen UART, gelle? Und wenn man Daten mit einem PC austauscht, dann geht sowas wie Timeouts sowieso nicht, denn das Programm im PC läuft ja sowieso nur in den Zeitabschnitten, die es vom BS zugeteilt bekommt. Also: Was du brauchsr, ist ein Protokoll. Beispielsweise kannst du als allersimpelste Methode folgende Festlegung treffen: a) von den 256 möglichen Codes guckst du dir 2 Codes aus, die was Besonderes sein sollen. Der eine besondere Code ist das Synchronisierzeichen. Der andere besondere Code ist ein Anzeiger, daß nach ihm 2 Zeichen kommen, die jeweils ein Hex-Nibble enthalten, die im Empfänger zusammengesetzt werden müssen und damit ein übertragenes Byte ergeben. Damit sind dann auch die Codes der zwei besonderen Zeichen sendbar (eben in Form von 3 Bytes: Markierung, hex, hex). W.S.
W.S. schrieb: > Zweitens: Was hier an Vorschlägen kam über Timeouts usw. ist Mumpitz. > Schließlich reden wir hier über den Datenverkehr über einen UART, > gelle? Und wenn man Daten mit einem PC austauscht, dann geht sowas wie > Timeouts sowieso nicht, denn das Programm im PC läuft ja sowieso nur in > den Zeitabschnitten, die es vom BS zugeteilt bekommt. geht bei mir sehr gut. Und man muss IMMER mit Timeouts arbeiten. Wenn der PC zum client eine Anfrage schickt und darauf eine Antwort erwarten - wie lange willst du ihn denn warten lassen ohne Timeout? man muss also auf dem PC eine Timeout für eine Antwort festlegen, damit es irgendwann weiter geht. Und in dieser Zeit erfolgt keine Datenübertragung auf dem Bus (PC warten ja). Und diese Lücke kann der client nutzen um seine Packet-State-Machine zurückzusetzen. Denn nach der Lücke kommt auf jeden Fall der Anfang von einem Packet.
W.S. schrieb: > DruckPause schrieb: >> Versteht ihr was ich meine? > > Ja. Du hast eine grundfalschen Denkansatz. > > Also erstens: Wenn du alle möglichen Bytes 0..255 für alles zuläßt, dann > hast du garkeine Möglichkeit zu irgendwelcher Kontrolle, außer solchen > Methoden, wie sie z.B. beim RDS Dekodieren angesagt sind, wo also über > eine Vielzahl von empfangenen Bits ein bestimmtes Muster gesucht wird > zur Synchronisation. Oder Escapen, wie ich weiter oben vorgeschlagen hatte. GAR KEINE ist hier komplett falsch. gruß cyblord
W.S. schrieb: > Der andere besondere Code ist ein Anzeiger, daß > nach ihm 2 Zeichen kommen, die jeweils ein Hex-Nibble enthalten, die im > Empfänger zusammengesetzt werden müssen und damit ein übertragenes Byte > ergeben. Damit sind dann auch die Codes der zwei besonderen Zeichen > sendbar (eben in Form von 3 Bytes: Markierung, hex, hex). > > W.S. Hm, das mußt du nochmal erklären. Ich glaub das geht so nicht, zumindest nicht ohne Einschränkung. Ich stell mir vor: mein Sync-Zeichen ist 0x05, mein "2-Nibble-Anzeiger" ist 0x06. Jetzt möchte ich das Zeichen 0x56 senden. Dann sieht mein Datenstrom nach deiner Idee doch so aus: 0x05 - 0x06 - 0x05 - 0x06 | | | '----- Nibble 2 | | '------------ Nibble 1 | '------------------- 2-Nibble-Anzeiger '-------------------------- Sync oder? Dann hab ich aber zweimal hinereinander Sync und den 2-Nibble-Anzeiger. Und dann ist Feierabend. Geht das nicht nur dann, wenn meine beiden Sonderzeichen größer 0x0F sind? Gruß, Joachim
Joachim schrieb: > Hm, das mußt du nochmal erklären. Ich glaub das geht so nicht, zumindest > nicht ohne Einschränkung. Sagen wir so: Du hast einen Fall konstruiert, bei dem diese Form des Escapens unsinnig ist. > Ich stell mir vor: mein Sync-Zeichen ist 0x05, Wähle ein anderes Sync-Zeichen. Zb 0xFF (in der Praxis nicmmt man eines, von dem man erwartet, dass es in den Daten nicht nicht oft vorkommen wird > mein "2-Nibble-Anzeiger" ist 0x06. wähle 0xFE > Jetzt möchte ich das Zeichen 0x56 Wäre in deinem Fall kein Problem, weil 0x56 bei dir weder Sync-Zeichen noch Escape Zeichen ist. Mit 0x56 machst du also gar nichts. Das wird so gesendet wie alles andere. Aber sagen wir mal, ich will 0xFF in den Daten senden. Anstelle von 0xFF wird dann (in diesem Schema) gesendet 0xFE 0x0F 0x0F
Peter II schrieb: > Reinhard Kern schrieb: >> Du willst also immer einen Fehler provozieren, damit das folgende Paket >> synchronisiert werden kann? Wie verträgt sich das mit der von dir >> (unnötigerweise) geforderten Effektivität? > > was für ein Fehler provozieren? > > Wenn nur das halbe Packet, wegen einen kabel fehler, nicht bei client > ankommt hat nicht mit Fehler provozieren zu tun? Und wie synchronisierst du dich neu in den Datenstrom? Antwort bei dir: Indem ich den Sender zwinge, nach einem Telegram eine Pause einzulegen, damit ich den Anfang des Pakets erkennen kann. (und ich rede von einem ununterbrochenem Datenstrom). Und da sorgst du dich um Effizenz? Effizenz in einem System, in dem du dem Sender vorschreibst, dass er Pausen machen muss?
Peter II schrieb: > Wenn der PC zum client eine Anfrage schickt und darauf eine Antwort > erwarten - wie lange willst du ihn denn warten lassen ohne Timeout? > > man muss also auf dem PC eine Timeout für eine Antwort festlegen das ist sowieso unbestritten. Dass man Timeouts vorsehen muss, ist kein Streipunkt. Nur wenn die Synchronisierung in deinem Protokoll einzig und alleine darauf beruhen, dass die Timeouts das regeln, dagegen hab ich einen Einwand. > es irgendwann weiter geht. Und in dieser Zeit erfolgt keine > Datenübertragung auf dem Bus (PC warten ja). Und diese Lücke kann der > client nutzen um seine Packet-State-Machine zurückzusetzen. Denn nach > der Lücke kommt auf jeden Fall der Anfang von einem Packet. Ach? Bei dir vielleicht. Bei mir nicht. Bei mir kann nach einer Lücke alles mögliche kommen, weil der Sender dauersendet und die Putzfrau das Kabel wieder eingesteckt hat. Und nu?
Karl Heinz Buchegger schrieb: > Und wie synchronisierst du dich neu in den Datenstrom? > > Antwort bei dir: Indem ich den Sender zwinge, nach einem Telegram eine > Pause einzulegen, damit ich den Anfang des Pakets erkennen kann. (und > ich rede von einem ununterbrochenem Datenstrom). > Und da sorgst du dich um Effizenz? Effizenz in einem System, in dem du > dem Sender vorschreibst, dass er Pausen machen muss? noch einmal: Der Sender muss warten weil er keine Antwort bekommen hat. Ich habe nicht geschrieben das der Sender nach jeden Packet eine Pausen machen muss. Die pause ergibt sich weil der client nicht antwortet. Diese geht nur wenn der Bus so ausgelegt ist, das der Master Anfrage schickt und dann auf eine Antwort wartet.
Karl Heinz Buchegger schrieb: > Sagen wir so: > Du hast einen Fall konstruiert, bei dem diese Form des Escapens unsinnig > ist. Hallo Karl Heinz! Das ist schon richtig, mein Beispiel war aber mit Absicht so gewählt. Ich wollte nur sicher gehen bzw. zeigen, daß das ja irgendwie nicht mit beliebigen Zeichen geht. Darum hab ich ja geschrieben, daß die "Sonderzeichen" größer als 0x0F sein müssen. So wie bei dir, mit den von dir gewählten Codes ist das natürlich möglich :) . Ich wollte nur nicht, daß das jemand ausversehen so macht, wie in meinem Beispiel und sich dann wundert, daß nix geht :) . Gruß, Joachim
Karl Heinz Buchegger schrieb: > Bei mir kann nach einer Lücke alles mögliche kommen, weil der Sender > dauersendet und die Putzfrau das Kabel wieder eingesteckt hat. Und nu? er sendet ja nicht dauert. Er will ja eine Antwort haben, also wartet er auch mal. Und wenn jemand das Kabel reinsteck während er gerade sendet (damit kommt nur der Rest vom Packet an) dann bekommt er keine Antwort. Das nächste Senden vom Master ist dann wieder ein vollständiges packet.
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.