In meiner UART-Kommunikation muss ich das Startbyte und das Stoppbyte der gesendeten Nachricht kennen. Das Startbyte ist einfach, das Stoppbyte jedoch nicht so sehr. Ich habe am Ende meiner Nachricht zwei Stoppbytes implementiert, nämlich \ n und \ r (10 und 13 Dezimalstellen). UART funktioniert nur mit Byte-Werten von 0 bis 255. Wie ausfallsicher ist das? Ich kann mir mit geringer Wahrscheinlichkeit vorstellen, dass meine Nachricht die Werte "10 und 13" nacheinander enthält, wenn sie nicht die Stoppbytes sind.
Gibt es einen besseren Weg, dies umzusetzen?
"\x0D\x0A"
.\r\n\r\n
welche die\n\r
Sequenz in der Mitte enthält ...Antworten:
Es gibt verschiedene Möglichkeiten, dies zu verhindern:
Wenn Ihre Nachrichten maximal 256 Byte groß sind, senden Sie:
Sie wissen also nach dem Empfang von 6 Datenbytes, dass dies das Ende ist. Sie müssen danach keine 10 13 senden. Und Sie können 10 13 innerhalb einer Nachricht senden. Wenn Ihre Nachrichten länger sein können, können Sie 2 Bytes für die Datengröße verwenden.
Update 1: Eine andere Möglichkeit, Pakete zu definieren
Eine andere Alternative besteht darin, Befehle zu senden, die eine bestimmte Länge haben und viele Abweichungen aufweisen können, z
Update 2: Schlechte Verbindungs- / Byteverluste
Alle oben genannten Funktionen funktionieren nur, wenn die UART-Zeile Bytes korrekt sendet. Wenn Sie zuverlässigere Versandmethoden verwenden möchten, gibt es auch viele Möglichkeiten. Nachfolgend einige:
Beachten Sie, dass alle oben genannten Mechanismen einfach oder so kompliziert sein können, wie Sie es möchten (oder müssen). Beim erneuten Senden einer Nachricht ist auch ein Mechanismus zum Identifizieren von Nachrichten erforderlich (z. B. Hinzufügen einer Sequenznummer zum Paket).
quelle
Wenn Sie senden, senden Sie beliebige Daten -> wahrscheinlich nicht ausfallsicher genug.
Eine übliche Lösung ist die Verwendung von Escape:
Definieren wir, dass die Zeichen 0x02 (STX - Frame-Start) und 0x03 (ETX - Frame-Ende) innerhalb des übertragenen Datenstroms eindeutig sein müssen. Auf diese Weise können Anfang und Ende einer Nachricht sicher erkannt werden.
Wenn eines dieser Zeichen innerhalb des Nachrichtenrahmens gesendet werden soll, wird es durch das Präfixieren eines Escapezeichens (ESC = 0x1b) und Hinzufügen von 0x20 zum ursprünglichen Zeichen ersetzt.
Originalzeichen ersetzt durch
Der Empfänger kehrt diesen Vorgang um: Jedes Mal, wenn er ein Escape-Zeichen empfängt, wird dieses Zeichen gelöscht und das nächste Zeichen von 0x20 subtrahiert.
Dies erhöht nur den Verarbeitungsaufwand, ist jedoch zu 100% zuverlässig (vorausgesetzt, es treten keine Übertragungsfehler auf, die Sie überprüfen können / sollten, indem Sie zusätzlich einen Prüfsummenmechanismus implementieren).
quelle
'\x10'
DLE (Data Link Escape). Einige der Wikipedia-Seiten weisen darauf hin, dass DLE häufig umgekehrt verwendet wurde: Das nächste Byte war eher ein Steuerzeichen als ein Datenbyte. Nach meiner Erfahrung ist das im Allgemeinen die entgegengesetzte Bedeutung für eine Flucht.Sie wissen, ASCII hat bereits Bytes für diese Funktionen.
Es enthält auch Codes für verschiedene Zwecke innerhalb der Nutzlast.
Ihr Protokoll sollte die feinste Granularität von ACK (0x06) und NAK (0x15) angeben, damit negativ bestätigte Daten erneut übertragen werden können. Bis zu dieser feinsten Granularität ist es ratsam, unmittelbar nach einem (nicht entkappten) Startindikator ein Längenfeld zu haben, und (wie in anderen Antworten erläutert) ist es ratsam, jedem (nicht entkappten) Stoppindikator einen CRC zu folgen.
quelle
UART ist von Natur aus nicht ausfallsicher - wir sprechen hier von der Technologie der 1960er Jahre.
Die Ursache des Problems liegt darin, dass UART nur einmal pro 10 Bit synchronisiert wird, sodass zwischen diesen Synchronisierungsperioden viel Kauderwelsch übertragen werden kann. Im Gegensatz zu beispielsweise CAN, das jedes einzelne Bit mehrmals abtastet.
Jeder in den Daten auftretende Doppelbitfehler beschädigt einen UART-Frame und wird unentdeckt übergeben. Bitfehler in Start / Stopp-Bits können in Form von Überlauffehlern erkannt werden oder nicht.
Unabhängig davon, ob Sie Rohdaten oder Pakete verwenden, besteht daher immer die Wahrscheinlichkeit, dass durch EMI verursachte Bitflips zu unerwarteten Daten führen.
Es gibt zahlreiche Möglichkeiten der "traditionellen UART-Quacksalberei", um die Situation geringfügig zu verbessern. Sie können Synchronisationsbytes, Synchronisationsbits, Paritätsbits und Doppelstoppbits hinzufügen. Sie können Prüfsummen hinzufügen, die die Summe aller Bytes zählen (und diese dann invertieren - warum nicht), oder Sie können die Anzahl der binären als Prüfsumme zählen. All dies ist weit verbreitet, äußerst unwissenschaftlich und mit einer hohen Wahrscheinlichkeit fehlender Fehler. Aber das war es, was die Leute von 1960 bis 1990 taten und vieles mehr seltsame Dinge wie diese leben heute weiter.
Der professionellste Weg, um mit der sicheren Übertragung über UART umzugehen, ist eine 16-Bit-CRC-Prüfsumme am Ende des Pakets. Alles andere ist nicht sehr sicher und es besteht eine hohe Wahrscheinlichkeit, dass Fehler fehlen.
Auf Hardwareebene können Sie dann das Differential RS-422 / RS-485 verwenden, um die Robustheit des Getriebes drastisch zu verbessern. Dies ist ein Muss für eine sichere Übertragung über größere Entfernungen. UART auf TTL-Ebene sollte nur für die Kommunikation an Bord verwendet werden. RS-232 sollte nicht für andere Zwecke als zur Abwärtskompatibilität mit alten Sachen verwendet werden.
Insgesamt ist Ihr Fehlererkennungsmechanismus umso effektiver, je näher er an der Hardware liegt. In Bezug auf die Effektivität addieren sich die Differenzsignale am meisten, gefolgt von der Überprüfung auf Rahmen- / Überlauffehler usw. CRC16 fügt einige hinzu, und dann fügt "traditionelle UART-Quacksalberei" ein wenig hinzu.
quelle
Eine Situation, in der ein Teil der Daten gleich der Abschlusssequenz ist, sollte beim Entwerfen des Formats eines seriellen Datenpakets berücksichtigt werden. Eine andere zu berücksichtigende Sache ist, dass jedes Zeichen während der Übertragung beschädigt werden oder verloren gehen kann. Ein Startzeichen, ein Stoppzeichen, ein Datennutzlastbyte, eine Prüfsumme oder ein CRC-Byte sowie ein Vorwärtsfehlerkorrekturbyte sind nicht immun gegen Korruption. Der Framing-Mechanismus muss erkennen können, wenn ein Paket beschädigte Daten enthält.
Es gibt verschiedene Möglichkeiten, dies alles anzugehen.
Ich gehe davon aus, dass Pakete nur mit den seriellen Bytes umrahmt werden. Handshake-Linien werden nicht zum Einrahmen verwendet. Zeitverzögerungen werden nicht für die Gestaltung verwendet.
Paketlänge senden
Senden Sie die Länge des Pakets am Anfang anstelle des Abschlusszeichens am Ende.
Profis: Payload wird in einem effizienten Binärformat gesendet.
Nachteile: Sie müssen die Paketlänge zu Beginn der Übertragung kennen.
Entkomme den Sonderzeichen
Entfliehen Sie beim Senden der Nutzdaten den Sonderzeichen. Dies wurde bereits in einer früheren Antwort erläutert .
Vorteile: Der Absender muss die Länge des Pakets zu Beginn der Übertragung nicht kennen.
Nachteile: Etwas weniger effizient, je nachdem, wie viele Nutzlastbytes maskiert werden müssen.
Payload-Daten sind so codiert, dass sie keine Start- und Stoppzeichen enthalten können
Die Nutzdaten des Pakets sind so codiert, dass sie keine Start- oder Stoppzeichen enthalten können. Normalerweise erfolgt dies durch Senden von Nummern als ASCII- oder Hex-ASCII-Darstellung.
Profis: Mit gängigen Terminalprogrammen lesbar. Es ist kein Code erforderlich, um das Entkommen zu handhaben. Sie müssen die Länge des Pakets zu Beginn der Übertragung nicht kennen
Nachteile: Geringere Effizienz. Für ein Byte Nutzdaten werden mehrere Bytes gesendet.
quelle