Forum: Mikrocontroller und Digitale Elektronik UART Übertragung Ende feststellen


von BetonMicha (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit meiner UART Übertragung. Ich sende Kommandos 
von meinem Smartphone zu meinem AVR und vom AVR zurück zum Smartphone. 
Das funktioniert auch super.
Damit ich das eine eines Kommandos erkenne, benutze ich im Moment das 
Byte 0x04. Jetzt hab ich allersings das Problem, dass ich dem 
Mikrocontroller eine Adresse übergebe, in der 0x04 vorkommt. Da ein 
Kommando immer aus 5 Bytes besteht, hab ich einfach auf 0x04 und länge 
überprüft. Ich möchte allerdings auch Daten senden, die länger als 5 
Byte sein können.

Wie kann ich das Ende zuverlässig feststellen?

mfg Micha

von Karl H. (kbuchegg)


Lesenswert?

Indem du 1 Zeichen definierst, welches in den Daten nicht vorkommen 
darf. Sollte dieses Byte tatsächlich in den Daten vorkommen, musst du es 
soweit verändern, dass
* der Empfänger feststellen kann, dass es entsprechend modifiziert wurde
* die Veränderung rückgängig machen kann.

Du könntest zb folgendes vereinbaren.

In den Daten selber darf ein 0x04 nicht vorkommen. Sollte es doch 
vorkommen, dann schickst du statt dessen ein 0x05. Um jetzt die 0x04 von 
0x05 unterscheiden zu können, schickst du nach einem 0x05 noch ein 
zusätzliches Byte, welches beim Empfänger klarstellt ob das empfangene 
0x05 tatsächlich ein 0x05 war oder ob es sich um ein 0x04 gehandelt hat.

zb
du willst übertragn

  0x34 0x56 0x45 0x34

da kein 0x04 da drinnen vorkommt, überträgst du

  0x34 0x56 0x45 0x34 0x04

das 0x04 zeigt dem Empfänger an: Ende der Nachricht.

Jetzt willst du übertragen


  0x08 0x04 0x45 0x34

da kommt ein 0x04 vor. Das darf nicht sein. Du ersetzt die 0x04 durch 
0x05 0x01 und überträgst

  0x08 0x05 0x01 0x45 0x34 0x04

in den Daten kommt kein 0x04 vor, der Empfänger weiß, das er nach einem 
0x05 sich noch das nächste Byte ansehen muss, und wenn dieses 0x01 ist, 
dann muss die Sequenz 0x05 0x01 in den Daten nach dem Empfang durch 0x04 
ersetzt werden.

Du willst übertragen

  0x08 0x04 0x45 0x05

wieder: die 0x04 werden durch die Sequenz 0x05 0x01 ersetzt. Zusätzlich 
muss auch 0x05 durch 0x05 0x02 ersetzt werden. Du überträgst daher

  0x08 0x05 0x01 0x45 0x05 0x02 0x04

Die 0x04 zeigen wieder das Ende an. Der Empfänger ersetzt 0x05 0x01 
durch 0x04 und er ersetzt 0x05 0x02 durch ein einzelnes 0x05. Er erhält 
daher als übertragene Daten

  0x08 0x04 0x45 0x05

welches auffallend den zu übertragenden Daten entspricht.

von Joachim (Gast)


Lesenswert?

Du kannst auch eine Zeichenfolge als Ende definieren. So hab ich das 
auch gemacht, nur eben um den Beginn einer Nachricht klar zu erkennen. 
Wenn du eine Zeichenfolge als Ende-Markierung benutzt, dann ist die 
Chance deutlich geringer, daß diese Zeichenfolge in deinen Nutzdaten 
vorkommt :)

von BetonMicha (Gast)


Lesenswert?

Ok das hört sich schonmal gut an.

Mir fällt gerade noch ein, ich könnte weiterhin das Byte 0x04 als Ende 
definieren und bei meinen Kommandos zusätzlich auf länge prüfen. Und bei 
meinen Daten ebenfalls das 0x04 benutzen, da es dort nicht vorkommt. 
Also 0x04 erst als Endbyte interpretieren wenn Pos >= 6 ist (5 Byte für 
Kommando abziehen). Dann müssten meine Daten nur mindestens 5 Byte lang 
sein, was aber kein Problem darstellt.

Ich werde mal die hier vrogeschlagenen Verfahren testen. Mal sehen 
welches am effektivsten ist.

von Karl H. (kbuchegg)


Lesenswert?

BetonMicha schrieb:
> Ok das hört sich schonmal gut an.
>
> Mir fällt gerade noch ein, ich könnte weiterhin das Byte 0x04 als Ende
> definieren und bei meinen Kommandos zusätzlich auf länge prüfen. Und bei
> meinen Daten ebenfalls das 0x04 benutzen, da es dort nicht vorkommt.
> Also 0x04 erst als Endbyte interpretieren wenn Pos >= 6 ist (5 Byte für
> Kommando abziehen). Dann müssten meine Daten nur mindestens 5 Byte lang
> sein, was aber kein Problem darstellt.

Nicht zuviel künsteln.
Die Ersetzung kannst du ganz tiefen unten in deiner Aufrufhierarchie 
sowohl beim Sender als auch beim Empfänger erledigen. Darüber liegende 
Schichten müssen davon überhaupt nichts mitkriegen.

von ... (Gast)


Lesenswert?

ich habe für die Datenübertragung von einem Gerät zum PC und zurück über 
UART folgende Vereinbarung:

Erst kommt die Länge des Datensatzes (bei mir 1 Byte), dann eine Kennung 
für die Art der übertragenen Daten, danach die Daten und dann noch 
CR/LF, damit ich mir das notfalls mit einem Editor ansehen kann. Am Ende 
eines Datenfeldes kommt dann noch eine Zeile, in der der CRC aller 
vorigen Datenbytes des Datenfeldes steht.

Diese Art der Datenübertragung per UART wird sehr häufig angewandt.

Als Endebedingung ist die zweimalige Übertragung der Zeile 0x04 0x00 0xD 
0x0A (Länge 4, null Datenbytes, Zeilenabschluss) definiert.

von Ich (Gast)


Lesenswert?

Joachim schrieb:
> dann ist die
> Chance deutlich gering_er_

Es ist aber immer noch Wahrscheinlichkeitsglücksspiel. Karl Heinz 
Bucheggers Methode nicht.

von uwe (Gast)


Lesenswert?

Startbyte - Länge - Daten(z.B. Befehl+Param1+Param2+...)- checksum
Man sollte schon ein Startbyte haben, da wenn das Erste Byte Fehlerhaft 
ist (und das kann beim Stecken von Steckern usw. passieren) die Empfangs 
Statemachine gestartet wird und eventuell mit einem falschen und großen 
Wert gefüttert wird. Danach müssen erst mal soviele Bytes empfangen 
werden wie gefordert oder ein Timeout ausgelößt werden, bevor wieder 
etwas neues gesendet werden kann.

von BetonMicha (Gast)


Lesenswert?

Vielen Dank für eure Antworten.
Ich habe jetzt die Methode von Karl Heinz Buchegger benutzt und es läuft 
sehr gut! :)
Wenn der Code nicht mehr Quick 'n Dirty ist, dann poste ich ihn hier. 
Vielleicht braucht ihn ja noch jemand anderes.

Ein Startbyte werde ich aber auch noch einführen. Ist mir im Moment noch 
nicht so wichtig, weil es egal ist, ob mal ein Befehl verloren geht.

von Moby (Gast)


Lesenswert?

Hallo, wenn man nicht bestimmte Bytes für irgendwelche Kennungen 
verbrauchen will bzw. für beliebige Bytefolgen installiert man am besten 
einen Timer der solange neu gesetzt wird wie Bytes eintreffen und bei 
Ablauf das Übertragungsende anzeigt!

von Karl H. (kbuchegg)


Lesenswert?

Moby schrieb:
> Hallo, wenn man nicht bestimmte Bytes für irgendwelche Kennungen
> verbrauchen will bzw. für beliebige Bytefolgen installiert man am besten
> einen Timer der solange neu gesetzt wird wie Bytes eintreffen und bei
> Ablauf das Übertragungsende anzeigt!

Timer ja.
Aber um eine fehlerhafte Übertragun zu erkenne, die aus irgendeinem 
Grund mitten drinn abgerissen ist.

Zur Erkennung des regulären Übertragungsendes und als Aussage, dass 
jetzt ein Datensatz komplett angekommen ist, taugt das nichts.

von Volker S. (volkerschulz)


Lesenswert?

Karl Heinz Buchegger schrieb:
> [...]
> Zur Erkennung des regulären Übertragungsendes und als Aussage, dass
> jetzt ein Datensatz komplett angekommen ist, taugt das nichts.

Naja, je nach Sende-Logik schon... ;)

Volker

von Karl H. (kbuchegg)


Lesenswert?

Volker Schulz schrieb:
> Karl Heinz Buchegger schrieb:
>> [...]
>> Zur Erkennung des regulären Übertragungsendes und als Aussage, dass
>> jetzt ein Datensatz komplett angekommen ist, taugt das nichts.
>
> Naja, je nach Sende-Logik schon... ;)

Bis dann jemand kommt und den UART Stecker zieht. Oder die Funkstrecke 
gestört wird oder ....

Ausserdem ist es lästig, wenn man nach einer Message erst mal eine 
Zwangspause einlegen muss bis die nächste Message beginnen darf.

Ein Timeout kann man benutzen um festzustellen ob die Gegenstelle noch 
da ist. Aber zur Synchronisierung ist es kein wirklich taugliches 
Mittel, weil du nie weißt, ob die Pause jetzt gewollt ist, oder nur 
deshalb entstanden ist, weil die Gegenstelle nicht mehr da ist (aus 
welchem Grund auch immer). Nich umsonst sagt man beim Funk 'Over' wenn 
man der Gegenstelle signalisieren will, dass sie jetzt quatschen kann 
und legt nicht einfach nur eine Pause ein.

von Volker S. (volkerschulz)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Volker Schulz schrieb:
>> Karl Heinz Buchegger schrieb:
>>> [...]
>>> Zur Erkennung des regulären Übertragungsendes und als Aussage, dass
>>> jetzt ein Datensatz komplett angekommen ist, taugt das nichts.
>>
>> Naja, je nach Sende-Logik schon... ;)
>
> Bis dann jemand kommt und den UART Stecker zieht. Oder die Funkstrecke
> gestört wird oder ....

Bei gestoerter Funkstrecke oder gerade erst wieder eingestecktem 
UART-Stecker hast Du im Zweifel bei Terminierung via Zeichen das gleiche 
Problem. Die "Zeitmethode" wird selbst im sicherheitskritischen 
militaerischen Bereich angewendet, natuerlich nicht ohne weitere 
Sicherheitsmechanismen wie einem 8-Bit-XOR als Checksumme und/oder 
Plausibilitaespruefung ueber mehrere Datensaetze.

Volker

von Volker S. (volkerschulz)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ein Timeout kann man benutzen um festzustellen ob die Gegenstelle noch
> da ist. Aber zur Synchronisierung ist es kein wirklich taugliches
> Mittel, weil du nie weißt, ob die Pause jetzt gewollt ist, oder nur
> deshalb entstanden ist, weil die Gegenstelle nicht mehr da ist (aus
> welchem Grund auch immer). Nich umsonst sagt man beim Funk 'Over' wenn
> man der Gegenstelle signalisieren will, dass sie jetzt quatschen kann
> und legt nicht einfach nur eine Pause ein.

Deswegen schrieb ich ja "je nach Sende-Logik". Wir haben durchaus 
Messmodule, die ihre Werte alle X Millisekunden ueber die RS232 spucken. 
Wo liegt da das Problem?

Volker

von Karl H. (kbuchegg)


Lesenswert?

Volker Schulz schrieb:
> Karl Heinz Buchegger schrieb:
>> Volker Schulz schrieb:
>>> Karl Heinz Buchegger schrieb:
>>>> [...]
>>>> Zur Erkennung des regulären Übertragungsendes und als Aussage, dass
>>>> jetzt ein Datensatz komplett angekommen ist, taugt das nichts.
>>>
>>> Naja, je nach Sende-Logik schon... ;)
>>
>> Bis dann jemand kommt und den UART Stecker zieht. Oder die Funkstrecke
>> gestört wird oder ....
>
> Bei gestoerter Funkstrecke oder gerade erst wieder eingestecktem
> UART-Stecker hast Du im Zweifel bei Terminierung via Zeichen das gleiche
> Problem.

Nein hab ich nicht.
Nach einem Übertragungsfehler wird alles bis zum Startbyte verworfen, 
wenn es ein Startbyte gibt. Gibt es kein dezidiertes Startbyte, dann 
wird alles bis zum nächsten Endbyte als ungültig verworfen. Und da die 
eindeutig sind, kann man die im (nicht gestörte Übertragung 
vorausgesetzt) Datenstrom immer eindeutig erkennen.
Egal ob Startbyte oder Endbyte, auf jeden Fall kann ich die Übertragung 
danach mit 100% Sicherheit wieder synchronisieren.

Hatten wir letztens erst wieder.
Die Abfrage eines entfernten Servers ist mit einem Timeout gesichert. 
Beim Abholen der Daten sind wir in einen Timeout gelaufen, der als 
solcher auch korrekt als Timeout Fehler in der Übertragung 
diagnostiziert wurde. Wenn es nach euch geht, hätten wir mit dem Timeout 
die Übertragung als abgeschlossen betrachten müssen und sagen sollen 
"das wars, mehr Daten liegen am Server nicht vor". In Wirklichkeit hat 
der Server einfach nur ein wenig länger zum Bereitstellen der Daten 
gebraucht.

von Karl H. (kbuchegg)


Lesenswert?

Das man einen Datensatz noch zusätzlich ein Schema aufprägen kann, 
welches man testen kann, ist auch klar. Selbstverständlich verlässt sich 
kein Mensch darauf, dass das Ausbleiben eines Timeout eine saubere 
Übertragung garantiert.

von Volker S. (volkerschulz)


Lesenswert?

Karl Heinz Buchegger schrieb:
> [...]
> Nach einem Übertragungsfehler wird alles bis zum Startbyte verworfen,
> wenn es ein Startbyte gibt. Gibt es kein dezidiertes Startbyte, dann
> wird alles bis zum nächsten Endbyte als ungültig verworfen. [...]

Gleiches in meinem Falle. Ist das letzte Byte nicht das XOR der 
vorherigen Bytes, wird der Datensatz verworfen und es geht nach der 
Pause erfolgreich weiter. Nun kann es natuerlich passieren dass das XOR 
rein zufaellig auf die invaliden Daten passt. Aber auch bei Deiner Idee 
koennte zufaellig ein Startbyte gesendet werden, das keins war aber nur 
als solches zu erkennen ist, weil das vorherige (verlorene) Byte die 
Maske war.


> Hatten wir letztens erst wieder.
> Die Abfrage eines entfernten Servers ist mit einem Timeout gesichert.
> Beim Abholen der Daten sind wir in einen Timeout gelaufen, der als
> solcher auch korrekt als Timeout Fehler in der Übertragung
> diagnostiziert wurde. Wenn es nach euch geht, hätten wir mit dem Timeout
> die Übertragung als abgeschlossen betrachten müssen und sagen sollen
> "das wars, mehr Daten liegen am Server nicht vor". In Wirklichkeit hat
> der Server einfach nur ein wenig länger zum Bereitstellen der Daten
> gebraucht.

Deswegen schrieb ich ja explizit "je nach Sende-Logik". Wenn auch 
waehrend der regulaeren Uebertragung Pausen von gleicher Laenge wie bei 
der Trennpause auftreten koennen, macht das natuerlich wenig Sinn.

Volker

von Karl H. (kbuchegg)


Lesenswert?

Volker Schulz schrieb:
> Karl Heinz Buchegger schrieb:
>> [...]
>> Nach einem Übertragungsfehler wird alles bis zum Startbyte verworfen,
>> wenn es ein Startbyte gibt. Gibt es kein dezidiertes Startbyte, dann
>> wird alles bis zum nächsten Endbyte als ungültig verworfen. [...]
>
> Gleiches in meinem Falle. Ist das letzte Byte nicht das XOR der
> vorherigen Bytes, wird der Datensatz verworfen und es geht nach der
> Pause erfolgreich weiter. Nun kann es natuerlich passieren dass das XOR
> rein zufaellig auf die invaliden Daten passt. Aber auch bei Deiner Idee
> koennte zufaellig ein Startbyte gesendet werden, das keins war aber nur
> als solches zu erkennen ist, weil das vorherige (verlorene) Byte die
> Maske war.

Ich sag nicht, dass im Datensatz keine Check-Mechanismen vorhanden sind.
Die spielen eine Ebene höher.
Hier geht es um die Aufteilung eines Datenstroms in Datenframes. Und 
zwar im allgemeinen Fall.

Wenn ich einen Sensor aufs AUg gedrückt bekomme, der Pausen macht kann 
ich eh nichts dagegen tun. Wenn ich das aber steuern kann, werd ich 
einen Teufel tun und mir künstliche Übertragungspausen ins System holen.

von Volker S. (volkerschulz)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wenn ich einen Sensor aufs AUg gedrückt bekomme, der Pausen macht kann
> ich eh nichts dagegen tun. Wenn ich das aber steuern kann, werd ich
> einen Teufel tun und mir künstliche Übertragungspausen ins System holen.

Also in 99% der Spezifikationen von Messsonden (die ich auf meinen 
Schreibtisch bekomme) ist die Wiederholungsrate von vornherein 
festgelegt und fuehrt somit automatisch zu Zwangspausen... In einem 
solchen Falle kann man die durchaus sinnvoll nutzen...

Volker

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Wenn man schon die ASCII-Tabelle für die Ende-Kennung nimmt, dann muß 
man auch die ASCII-Tabelle für die restlichen Daten verweden. Also: 
Datenübertragung als ASCII-Zeichen.

Der Binärwert 0000_0100 wird also mit Endekennung nicht als 0x04 0x04 
übertragen, sondern als die drei "Buchstaben": '0', '4', 0x04

Der Binärwert 1100_0110 wäre dann 'B', '6', 0x04

Volker Schulz schrieb:
> Ist das letzte Byte nicht das XOR der vorherigen Bytes, wird der
> Datensatz verworfen und es geht nach der Pause erfolgreich weiter.
Auch die Prüfsumme müsste dann logischerweise als zwei Zeichen und nicht 
als ein Byte versendet werden.

... schrieb:
> Erst kommt die Länge des Datensatzes (bei mir 1 Byte), dann eine Kennung
> für die Art der übertragenen Daten, danach die Daten und dann noch
> CR/LF, damit ich mir das notfalls mit einem Editor ansehen kann.
Aber was macht das Terminal, wenn vor dem CR/LF schon Sonderzeichen 
kommen?
Ergo: wenn ich mit dem Terminalprogramm mitlesen möchte (und das ist 
eine sehr schöne Sache), muss ich mich auf "richtige" ASCII-Zeichen (von 
0..127) beschränken.

Moby schrieb:
> Hallo, wenn man nicht bestimmte Bytes für irgendwelche Kennungen
> verbrauchen will bzw. für beliebige Bytefolgen
Dann nimmt man ein Protokoll, dass sowas abhandeln kann. Man sollte sich 
aber immer vergegenwärtigen, für WAS die verwendete Schnittstelle 
ursprünglich mal ausgelegt war. Und das war bei RS232 eben NICHT eine 
binäre Dtenübertragung. Deshalb bietet diese Schnttstlle von sich aus 
(abgesehen vom Parity) keine Fehlererkennungsmechanismen.
> installiert man am besten einen Timer der solange neu gesetzt wird
> wie Bytes eintreffen und bei Ablauf das Übertragungsende anzeigt!
Kreativ: eine künstliche Protokollverzögerung...

von Volker S. (volkerschulz)


Lesenswert?

Lothar Miller schrieb:
> Wenn man schon die ASCII-Tabelle für die Ende-Kennung nimmt, dann muß
> man auch die ASCII-Tabelle für die restlichen Daten verweden. Also:
> Datenübertragung als ASCII-Zeichen.
>
> Der Binärwert 0000_0100 wird also mit Endekennung nicht als 0x04 0x04
> übertragen, sondern als die drei "Buchstaben": '0', '4', 0x04
>
> Der Binärwert 1100_0110 wäre dann 'B', '6', 0x04

Muss man nicht. Kann man natuerlich. Im NMEA-Protokoll ist fuer die 
Checksumme "HexASCII" vorgesehen (also das, was Du meinst), fuer die 
Nutzdaten ist die dezimale Schreibweise vorgesehen (getrennt durch 
Kommata) und es gibt definierte Start- und Stop-Bytes. Und, zu allem 
Ueberfluss, zwischen zwei Paketen (NICHT Saetzen) noch eine Zwangspause. 
;)

> ... schrieb:
>> Erst kommt die Länge des Datensatzes (bei mir 1 Byte), dann eine Kennung
>> für die Art der übertragenen Daten, danach die Daten und dann noch
>> CR/LF, damit ich mir das notfalls mit einem Editor ansehen kann.
> Aber was macht das Terminal, wenn vor dem CR/LF schon Sonderzeichen
> kommen?
> Ergo: wenn ich mit dem Terminalprogramm mitlesen möchte (und das ist
> eine sehr schöne Sache), muss ich mich auf "richtige" ASCII-Zeichen (von
> 0..127) beschränken.

Naja, wie toll kann ein Mensch im Terminalprogramm denn 0x00 mitlesen? 
CR ist auch nicht unbedigt zu erkennen wenn es alleine rumschwirrt (bzw. 
ist dann im Zweifel gar nichts mehr zu erkennen, weil ein Satz den 
vorherigen ueberschreibt). Man muesste sich dann schon auf's 
Alphanumerische beschraenken, den Rest kann man zum Steuern / Separieren 
benutzen.


> [...] Und das war bei RS232 eben NICHT eine
> binäre Datenübertragung. [...]

Sondern?


Volker

von Moby (Gast)


Lesenswert?

Man kann vielleicht zusammenfassen: Kommt immer auf den konkreten 
Anwendungsfall an. Die Timer-Methode bleibt hier aber die einfachste, 
universell verwendbare Lösung zur Erkennung des Übertragungsendes. Eine 
entsprechende Justage des Timers vorausgesetzt müssen auch keine 
nennenswerten Verzögerungen im Datentransfer die Folge sein. Für die 
eigentliche Prüfung der Datenvalidität sind dann natürlich andere 
Mechanismen vonnöten.

von Karl H. (kbuchegg)


Lesenswert?

Kopfschüttel

BTW: Bei NMEA dient die Pause nicht zur Satzendeerkennung. NMEA schickt 
da ganz banal ein \n als Satzende.
Die Pause ist willkommen um in dieser Zeit den Satz auszuwerten und 
dabei den Anfang des nächsten Satzes nicht zu verpassen.

Aber was red ich mir den Mund fusselig. Sagt mir einfach in welchen 
Produkten mit externem UART Anschluss euer Code drinnen ist, damit ich 
einen großen Bogen da drumm machen kann.

Und was an einer Timer Lösung einfach sein soll, gegenüber 6 Zeilen Code 
in den Sende/Empfangs Interrupts, die für die darüberliegenden Schichten 
völlig transparent auf der Übertragung ein oder zwei Bytewerte 
freischaufeln, entzieht sich meinem Verständnis.

Wenn ich, wie im Falle von zugekauften Sensoren, nicht auskann sieht es 
anders aus. Aber wenn ich es in der Hand habe Sender und Empfänger so 
zugestalten, wie ich will, werd ich mir doch nicht so eine Krücke ins 
Boot holen.

von Moby (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Aber wenn ich es in der Hand habe Sender und Empfänger so
> zugestalten, wie ich will,

Na aber sicher doch- Du mußt nur in der komfortablen Situation sein auch 
alles selbst in der Hand zu haben :) Aber das dürfte weder die Situation 
des TE sein als der übliche Normalfall, wo die eine Seite (zugekaufte 
Sensoren eben beispielsweise) vorgegeben ist.

Unstrittig ist für mich die Einfachheit der Timerlösung (meine Software 
hat auch nicht mehrere Schichten nötig :). Auch deshalb, weil 
Programmteile so wirkungsvoll voneinander entkoppelt werden was den Code 
letztlich übersichtlicher und robuster macht.

P.S. Keine Angst, verkaufen möcht ich Dir nichts :)

von Volker S. (volkerschulz)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Kopfschüttel
>
> BTW: Bei NMEA dient die Pause nicht zur Satzendeerkennung. NMEA schickt
> da ganz banal ein \n als Satzende.

Eigentlich ist es \r\n...


> Die Pause ist willkommen um in dieser Zeit den Satz auszuwerten und
> dabei den Anfang des nächsten Satzes nicht zu verpassen.

Die Pause findet man, wie oben erwaehnt, natuerlich nicht nach jedem 
Satz. Und ich habe ja auch nicht geschrieben dass diese Pause zum 
Erkennen verschiedener Pakete da ist, sondern dass sie schlichtweg 
aufgrund der Wiederholungsfrequenz gegeben ist.


> Und was an einer Timer Lösung einfach sein soll, gegenüber 6 Zeilen Code
> in den Sende/Empfangs Interrupts, die für die darüberliegenden Schichten
> völlig transparent auf der Übertragung ein oder zwei Bytewerte
> freischaufeln, entzieht sich meinem Verständnis.

Das "Einfache" verlagert sich in diesem Falle ganz klar auf den Sender. 
Die Timer-Empfangs-Logik mit Timer duerfte aber auch nicht viel mehr 
Codezeilen verschlingen.

Fuer den Fall dass wir uns missverstanden haben: Ich will hier 
keinesfalls die Pausen-Erkennung als tollste Loesung fuer jedes Problem 
bewerben (ganz im Gegenteil sogar), sie ist aber dennoch eine valide 
Option mit eigener Berechtigung. Und ist nicht nur in Theorie oder 
Bastelkeller anzutreffen.


> Wenn ich, wie im Falle von zugekauften Sensoren, nicht auskann sieht es
> anders aus. Aber wenn ich es in der Hand habe Sender und Empfänger so
> zugestalten, wie ich will, werd ich mir doch nicht so eine Krücke ins
> Boot holen.

Am bequemsten ist es natuerlich, die Daten "menschenlesbar", 
alphanumerisch zu uebertragen und Sonderzeichen als Steuer-Bytes zu 
verwenden. Wuerde ich wenn moeglich (gerade auch bei eigenen Projekten) 
auch so machen. Nun ist bequem nicht immer zwangslaeufig auch das 
sinnvollste. Und moeglich ist es eben auch nicht immer. ;)


Volker\r\n

von BetonMicha (Gast)


Lesenswert?

Hallo,

ist schon ein bisschen her, aber ich habe ja versprochen hier meine Code 
zu posten. Der Code für das Senden über UART ist in Java und der zum 
Empfang ist in C. Andersrum brauch ich das im Moment noch nicht, weil 
der Mikrocontroller nur Commandos erkennen muss, aber keine senden.

Java zum senden
1
byte[] buffer
2
3
// Changing 0x04 -> 0x05 0x01
4
// And changing 0x05 -> 0x05 0x02
5
for (int i = 0; i < buffer.length; i++) {
6
  if (buffer[i] == 0x04) {
7
    buffer[i] = 0x05;
8
    buffer = insertByte(buffer, (byte) 0x01, i + 1);
9
10
  } else if (buffer[i] == 0x05) {
11
    buffer = insertByte(buffer, (byte) 0x02, i + 1);
12
  }
13
}
14
15
// Adding 0x04
16
buffer = insertByte(buffer, (byte) 0x04, buffer.length);

C zum Empfang. command und uartString sind volatile char[]
1
void decodeCommand() {
2
  int j = 0;
3
4
  for (int i = 0; i < UART_MAXSTRLEN + 2; i++) {
5
    if ((j < 5) && (i < UART_MAXSTRLEN + 1)) {
6
      if (uartString[i] == 0x05) {
7
        switch (uartString[i + 1]) {
8
        case 0x01:
9
          command[j] = 0x04;
10
          i++;
11
          break;
12
        case 0x02:
13
          command[j] = 0x05;
14
          i++;
15
          break;
16
        default:
17
          break;
18
        }
19
      } else {
20
        command[j] = uartString[i];
21
      }
22
    }
23
24
    j++;
25
  }
26
}

Fuktioniert bei mir super. Fehlt nur noch ein Startbyte. Aber bei mir 
geht im Mikrocontroller nur der erste Befehl in die Hose. Die folgenden 
werden richtig erkannt, weil der UART dann synchronisiert ist.

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.