Forum: Mikrocontroller und Digitale Elektronik UART Übertragungsprotokoll, zwischen Daten/Befehlen unterscheiden


von Tycho B. (asellus)


Lesenswert?

Sehr geehrtes Forum,

ich bin auf ein interessantes Problem gestoßen und würde gern die 
Experten dazu befragen.
Es geht um Datenübertragung über USART des Atmega32. Ich habe 
festgestellt, dass beim Übertragen von Daten ich immer wieder das 
EOT-Signal bekomme, in meinem Fall das 0x0A, ohne das die Daten zu Ende 
sind. Im Nachhinein gesehen auch völlig zurecht, denn 0x0A ist ja auch 
ein gültiges Datenbyte:)
Problem erkannt, Gefahr aber noch nicht gebannt.
So wie ich das sehe gibt es zwei generelle Ansätze, zum Einen kann man 
an einer definierten Stelle, z.B. das erste Byte nach dem Header (ist 
also eine feste Position), die Länge der Daten angeben, zum Anderen kann 
man den Werteraum eines Bytes reduzieren und so Steuerzeichen 
vereinbaren.
Der erste Ansatz hat den geringsten Overhead, nur ein zusätzliches Byte 
pro Übertragung, allerdings ist die Verarbeitung etwas schwierig, und 
wenn die übrige Umgebung, die z.B. am selben seriellen Bus sitzt, 0x0A 
als Abschluss verlangt, dann wird's schwierig.

Jetzt kommen wir zu meiner Frage: Welche schnelle Kodierungen ohne zu 
großen Aufwand und Overhead gibt es überhaupt? Bei meiner Recherche bin 
ich auf folgende Möglichkeiten gestoßen:
1. Daten als ASCII-Werte übertragen. Da sehe ich nur Nachteile wie z.B. 
der riesige Overhead.
2. BCD-Code. Schon besser, allerdings relativ rechenintensiv.
Die nächsten habe ich mir ausgedacht:
3. Das Byte in zwei Bytes aufteilen, also jeweils die oberen vier Bits 
sind Daten, die unteren sind Steuerzeichen. Sehr einfach zu 
implementieren, jedoch doppelte Byteanzahl plus ein 0x0A.
4. z.B. das höchste Bit eines Bytes signalisiert, ob es ein Datenbyte 
ist oder ein Steuerzeichenbyte. Zusätzlich benötigt man also zu jeder 
Übertragung ein erstes Steuerzeichenbyte, welches max. 7 Bits enthält, 
und zwar die fehlenden höchsten Bits der Datenbytes. Und dann noch das 
letzte Steuerzeichen, 0x0A.
Verarbeitung relativ einfach, nur Bitschieben und ANDs, ORs usw. 2 Bytes 
Overhead. Ist auch einfach erweiterbar, wenn nach 7 Datenbytes kein 
0x0A, dann geht es weiter.

Liebes Forum, was gibt es noch für Möglichkeiten? Welche würdet Ihr 
bevorzugen?

Grüße
Tycho

Falls es von Interesse ist, der Header sieht so aus:
0:1=          ; Header, Karte:Befehl, beide einstellig
Daten
0x0A

von Stephan W. (sir_wedeck)


Lesenswert?

Hi,
schau dir mal die Protokolle Slip oder 3964R an.
Die Ersetzen die Steuerbytes, die im Datensatz vorkommen mit bestimmten 
Folgen von Bytes.

Slip:
-If any byte to be sent in the datagram is “192”, replace it with “219 
220”.
-If any byte to be sent is “219”, replace it with “219 221”.

Stephan

von Jörg S. (joerg-s)


Lesenswert?

Tycho B. schrieb:
> Der erste Ansatz hat den geringsten Overhead, nur ein zusätzliches Byte
> pro Übertragung, allerdings ist die Verarbeitung etwas schwierig,
In welcher hinsicht?

> wenn die übrige Umgebung, die z.B. am selben seriellen Bus sitzt, 0x0A
> als Abschluss verlangt, dann wird's schwierig.
Warum? Diese Geräte haben doch auch das Problem das sie das Ende nicht 
richtig erkennen würden.

> Liebes Forum, was gibt es noch für Möglichkeiten?
Z.B. bei auftauchen des Endezeichens im Datenfeld ein Byte-Muster 
erzeugen das sagt des es sich NICHT um das Datenende handelt.
So wie bei diesem Protokoll:
http://www.see-solutions.de/sonstiges/Protokollbeschreibung_ComfoAir.pdf
Ende ist 0x07 0x0F
Tauch im Datenbereich eine 0x07 auf, so wird dieses Byte auf 0x07 0x07 
verdoppelt.

von Muetze (Gast)


Lesenswert?

Moin,

also ich nutze für die Kommunikation über die UART meist das 
UDS-Protokoll, welches im Automobilbereich angesiedelt ist.
Da das UDS-Protokoll nicht die Übertragungsschicht definiert starte ich 
immer mit einem Byte zur Längenangabe und schließe das Datenpaket immer 
mit einer Checksumme ab. Es ist aber auch denkbar, ein Datenpaket mit 
einem Startbyte zu eröffen (z.B. 0xAA). Nötig ist es aber nicht.

Aufbau:
(Startbyte), Länge, Kommando, Identifier, Daten, Checksumme

Der Protokollaufbau ist auch für die Nutzung einer Eindratleitung (wie 
z.B. der K-Line) geeignet. So muss ich bei meinen Boxen nur eine 
"Diagnoseleitung" nach außen legen und kann mit einem einfachen 
RS232-K-Line-Adapter meine Boxen mit dem PC kontaktieren.
Auch ist es möglich mehrere teilnehmer an einem bus zu plazieren. Dann 
nutze ich das Startbyte als Adressbyte (0xFF = PC, 0x01 = Box 1, 02 = 
Box 2...).

Aufbau:
Adressbyte, Länge, Kommando, Identifier, Daten, Checksumme

Das UDS-Protokoll definiert dabei alles, was ich für eine Kommunikation 
mit meinem Mikrocontroller benötige. z.B.

Lesen/Schreiben von internen Informationen:
0x22 = ReadDataByIdentifier
0x2E = WriteDataByIdentifier

Lesen/Schreiben von Speicheradressen:
0x23 = readDataByAdress
0x3D = WriteDataByAdress

Für die Übertragung größerer datenblöcke
0x34 = RequestDownload
0x35 = RequestUpload
0x36 = TransferData
0x37 = RequestTransferExit

So gibt es auch Kommandos für die Ausführung von Routinen oder das 
direkte Ansteuern von Aktoren/Ausgängen.
Selbt verschiedene Diagnose-Level und die Nutzung von 
Zugriffsberechtigungen sind möglich.

Ich sehe in der Nutzung des UDS-Protokolls den großen Vorteil, dass es 
sich dabei um ein stabiles bewährtes Protokoll handelt, welches über 
eine ISO-Norm veröffentlicht ist. So ist es auch auf einfache Weise 
Möglich, dass man sich bei Prblemen mit dem Protokoll mit anderen Leuten 
beraten kann, ohne, dass man die jeweilige Implementierung im Detail 
kennen zu müssen. Mir hat dies schon mehrfach geholfen.

Bis denn dann und Grüße
Muetze

von Tycho B. (asellus)


Lesenswert?

Stephan W. schrieb:
> Hi,
> schau dir mal die Protokolle Slip oder 3964R an.
> Stephan

Zusätzliches Byte werden nur gesendet, wenn das Datenbyte 
zufälligerweise wie ein Steuerbyte aussieht. Das kenne ich nicht, klingt 
gut. Werde mir durch den Kopf gehen lassen.


Jörg S. schrieb:
> Tycho B. schrieb:
>> Der erste Ansatz hat den geringsten Overhead, nur ein zusätzliches Byte
>> pro Übertragung, allerdings ist die Verarbeitung etwas schwierig,
> In welcher hinsicht?
Naja, hauptsächlich bezogen auf Kommunikation mit Hardware, die das 
nicht kennt. Ich dachte, ich benutze meine Karte im c't-Lab, die senden 
aber, soweit ich mich richtig erinnere, alles ASCII und eben mit 0x0A 
als Abschluss.
>> wenn die übrige Umgebung, die z.B. am selben seriellen Bus sitzt, 0x0A
>> als Abschluss verlangt, dann wird's schwierig.
> Warum? Diese Geräte haben doch auch das Problem das sie das Ende nicht
> richtig erkennen würden.
Ja, ich habe die Benutzung mit c't-Karten nicht erwähnt, die hätten das 
Problem nicht.
Da hat man mehrere Karten am seriellen UART-Bus, Befehle und Rückgaben 
werden von Karte zu Karte bis zum PC durchgereicht.

>> Liebes Forum, was gibt es noch für Möglichkeiten?
> Z.B. bei auftauchen des Endezeichens im Datenfeld ein Byte-Muster
> erzeugen das sagt des es sich NICHT um das Datenende handelt.
> So wie bei diesem Protokoll:
> http://www.see-solutions.de/sonstiges/Protokollbeschreibung_ComfoAir.pdf
> Ende ist 0x07 0x0F
> Tauch im Datenbereich eine 0x07 auf, so wird dieses Byte auf 0x07 0x07
> verdoppelt.
Das geht in die Richtung von Stephan W., werde darüber nachdenken. 
Allerdings müsste ich dann 0x0A nicht verdoppeln, sondern ummappen, ist 
aber im Prinzip dasselbe.

@ Muetze
Das wäre ähnlich meinem ersten Vorschlag, mit der Angabe der Länge, 
andere Reihenfolge, standardisierte Befehle und Checksumme inklusive. 
Klappt aber wieder nicht mit dem bescheuerten 0x0A von c't.

von Peter R. (peterfido)


Lesenswert?

Hallo,

Wenn Du alles selbst baust, kannst Du Dir ein Protokoll aussuchen.
In einem Projekt habe ich Bit7 zur Erkennung von Daten genommen. Das hat 
den Nachteil, dass halt nur 128 verschiedene Werte übergeben werden 
können. Jedoch hat es für das Projekt ausgereicht. Vorteil ist, dass 
durch das gesetzte 7.Bit niemals ein 0A bzw 0D auftreten kann.


Sind fremde Bauteile mit am Lauschen, würde ich die ASCII Variante 
wählen. Da wird dann ein Byte schonmal 3 Byte lang, jedoch ist die 
Fehlerrate gegen 0. So verfahren auch viele kommerzielle Produkte, 
welche sich seriell parametrieren lassen.

von Sgix (Gast)


Lesenswert?

Man könnte auch beim USART des AVR den 9bit-Modus nutzen und das 9te Bit 
signalisiert dabei, ob es sich um Daten oder Befehle handelt.
Natürlich muss dann auch die Gegenstelle des AVRs den 9bit Modus 
unterstützen.

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.