Hallo, nur ne Frage bevor ich damit anfange.
Ich bekomme über'n Rs232 eine Zeichenkette, diese hat aber kein
Endzeichen, sondern es kommt kein Zeichen mehr.
Ich hab mir überlegt mit ner Schleifen die Zeichen hintereinander in ein
Arry zu schreiben. Somit wäre es gelöst aber umständlich, weil ich es
später wieder aus geben möchte.
Funktioniert dies auch mit net geänderten Version von :
1
voiduart_gets(char*Buffer,uint8_tMaxLen)
2
{
3
uint8_tNextChar;
4
uint8_tStringLen=0;
5
6
NextChar=uart_getchar();// Warte auf und empfange das nächste Zeichen
Jakob schrieb:> diese hat aber kein Endzeichen, sondern es kommt kein Zeichen mehr.
Nie mehr?
Sorry, aber die Frage drängt sich auf. Denn irgendwann mußt du doch mal
entscheiden, was zu tun ist mit den bisher empfangenen Zeichen. Es kann
ja auch sein, daß der sendende Part einfach mal paar Sekunden mit etwas
anderem beschäftigt ist und dann anschließend noch der Rest der
Zeichenkette kommt. In meinen Augen muß es entweder ein Ende-Zeichen
geben (0x00) oder die Länge der Zeichenkette muß mit übergeben werden
(wie bei Pascal-Strings). Nur so kann man sagen, daß die Zeichenkette
komplett übertragen wurde.
npn schrieb:> In meinen Augen muß es entweder ein Ende-Zeichen> geben (0x00) oder die Länge der Zeichenkette muß mit übergeben werden> (wie bei Pascal-Strings).
Naja, es muss ja nicht 0x00 sein. Die Beispielfunktion oben testet auf
'\r', was in vielen Fällen auch sinnvoll ist.
Wenn man kein Ende-Zeichen bekommt, muss man es mit einem Timeout
machen.
Also:
- Timer aufsetzen, Zähler hochzählen.
- Wenn Zähler einen Grenzwert erreicht -> Timeout!
- Wenn Timeout, dann String terminieren und Return.
@jakob. Die Software hängt im Abfragen des UART. Was soll passieren,
wenn das Endekriterium nicht erfüllt wird?
Im Augenblick passiert nix, der Prozessor hängt in der Schleife.
@npn: Es gibt viele Übertragungsprotokolle, die mit einem Timeout
arbeiten. Kommt eine gewisse Zeit (protokollabhängig) kein Zeichen, so
ist das Telegramm übertragen, oder fehlerhaft, das entscheidet dann die
Decoder-Software.
Frank M. schrieb:> npn schrieb:>> In meinen Augen muß es entweder ein Ende-Zeichen>> geben (0x00) oder die Länge der Zeichenkette muß mit übergeben werden>> (wie bei Pascal-Strings).>> Naja, es muss ja nicht 0x00 sein. Die Beispielfunktion oben testet auf> '\r', was in vielen Fällen auch sinnvoll ist.>> Wenn man kein Ende-Zeichen bekommt, muss man es mit einem Timeout> machen.>> Also:>> - Timer aufsetzen, Zähler hochzählen.> - Wenn Zähler einen Grenzwert erreicht -> Timeout!> - Wenn Timeout, dann String terminieren und Return.
Ja, okay. Klar geht auch jedes andere Zeichen, was sonst nicht im String
vorkommt. Das mit dem 0x00 war nur ein Beispiel, weil es ja naheliegend
ist, es als c-String zu übertragen.
Und mit dem Timeout kann man lediglich sagen: "Ich höre jetzt auf zu
warten". Aber anschließend kann ja vom Sender trotzdem noch der Rest der
Zeichenkette kommmen, der eigentlich noch dazu gehört. Da würde ich den
Timeout nur als "Reißleine" sehen, damit die gesamte Kommunikation nicht
hängenbleibt, wenn die Übertragung abreißt oder für eine bestimmte Zeit
unterbrochen wird. Diese Reißleine sollte man schon mit einbauen, das
ist klar. Aber sie stellt keine Erkennung des String-Endes dar.
Das mit dem Timer setzten klingt gut. dies werde ich dann ausprobieren.
Aber auch mal :
1
while(NextChar!='0x00'&&StringLen<MaxLen-1){
2
*Buffer++=NextChar;
3
StringLen++;
4
NextChar=uart_getchar();
Dann schreibt er ja nur dann in den String wenn Zeichen ankommen, sobald
dann kein Zeichen kommt müsste er aufhören Zeichen zulesen und den
String "Ausgeben"
Danke für die Tipp's
>> Dann schreibt er ja nur dann in den String wenn Zeichen ankommen,
Auch ein Zeichen mit dem ASCII Wert 0 ist ein Zeichen.
So etwas wie ein Zeichen, dass kein Zeichen darstellt, gibt es nicht.
Entweder es ist ein Zeichen angekommen oder es ist keines angekommen.
Wenn aber eines gekommen ist, dann war es ein Zeichen.
D.h. wenn schon, dann muss die uart_getchar Funktion bereits diese
Unterscheidung machen und dem Aufrufer mitteilen: es ist kein Zeichen
eingetroffen. Die Fleury UART Funktionen machen das zum Beispiel.
> dann kein Zeichen kommt müsste er aufhören Zeichen zulesen und den> String "Ausgeben"
und nein. das ist im allgemeinen keine gute Idee. Denn dann muss es eine
vereinbarten Zeitraum zwischen Empfänger und Sender geben. Der Sender
muss garantieren, dass er in einem bestimmten Zeitraum mit der Antwort
beginnt und er muss garantieren, dass zwischen der Übertragung 2-er
Zeichen nicht mehr als x Zeiteinheiten vergehen. Da die eigentliche
Übertragung sehr viel langsamer geht, als ein µC rechnet kannst du nicht
einfach sagen: wenn mit dem nächsten getchar() nichts gekommen ist, dann
erkläre ich den String als beendet. Das ist als ob du mittels berittenem
Boten zwischen Wien und Moskau kommunizierst. 5 Sekunden nachdem ein
Reiter eingetroffen ist erklärst du die Übertragung als beendet, dabei
hängt der nächste Reiter einfach nur in einem Vorort fest und dessen
Teil der Nachricht müsste auch noch mit dazu gehören. Du musst da schon
angemessene Zeiträume benutzen. Bei berittenen Reitern werden das wohl
ein paar Tage sein, die du einräumen musst.
Wenn du auf das Protokoll noch Einfluss nehmen kannst, dann dräng auf
ein Ende-Zeichen, dass dir unmissverständlich mitteilt: Jetzt ist die
Übertragung vollständig.
npn schrieb:> Und mit dem Timeout kann man lediglich sagen: "Ich höre jetzt auf zu> warten". Aber anschließend kann ja vom Sender trotzdem noch der Rest der> Zeichenkette kommmen, der eigentlich noch dazu gehört. Da würde ich den> Timeout nur als "Reißleine" sehen, damit die gesamte Kommunikation nicht> hängenbleibt, wenn die Übertragung abreißt oder für eine bestimmte Zeit> unterbrochen wird. Diese Reißleine sollte man schon mit einbauen, das> ist klar. Aber sie stellt keine Erkennung des String-Endes dar.
Bei einer zeitlichen Unterbrechung der Übertragung kann man nicht sicher
sagen, ob der später empfangene Rest noch zum bereits empfangenen Anfang
gehört oder ob es der Rest einer späteren Übertragung ist.
Die ungeplante Unterbrechung muss einen Grund haben und man sollte hier
auch mit Störungen rechnen. Und es ist somit nicht nur eine Reißleine um
das Programm am Laufen zu halten.
Frank M. schrieb:> Wenn man kein Ende-Zeichen bekommt, muss man es mit einem Timeout> machen.
Immer, oder ?
Was wenn das Ende Zeichen nicht kommt weil es verloren geht, oder wegen
CRC Fehler die Information über die Telegrammlänge unzuverlässig ist ?
Wie entscheide ich dann wann eine neuer String kommt ?
Michael Knoelke schrieb:> Wie entscheide ich dann wann eine neuer String kommt ?
Häufig wird nicht nur ein Ende-Zeichen, sondern auch ein Anfangszeichen
definiert.
Edit:
Da es hier um ASCII zu gehen scheint, verweise ich mal auf STX und ETX.
http://de.wikipedia.org/wiki/Steuerzeichen
Jakob schrieb:> Ich bekomme über'n Rs232 eine Zeichenkette, diese hat aber kein> Endzeichen, sondern es kommt kein Zeichen mehr.
Die Frage ist ja erstmal, wo kommen die Zeichen her? Welches Gerät
sendet die? Hast du die Möglichkeit, auf das Sendeformat Einfluß zu
nehmen? Wenn ja, dann würde ich auf jeden Fall ein "String-Ende-Zeichen"
einbauen. Oder noch besser, wie es Steffen vorgeschlagen hat, mit
Steuerzeichen wie <stx> und <etx> arbeiten.
Wenn du diese Möglichkeit nicht hast, kannst du dann eine Aussage
treffen, wann eine Zeichenkette als "beendet" erklärt werden kann? Das
heißt, wenn kein Zeichen mehr kommt, nach welcher Zeit man davon
ausgeht, daß später kommende Zeichen dann schon zu einer neuen
Zeichenkette gehören?
Ich bekomme das Gerät erst später und es nicht möglich etwas dran zu
ändern.
Ich wollte nur Infos sammeln, denn dies wäre eine Möglichkeit die
eintreffen könnte. Kann auch sein das nur eine bestimmt Anzahl an
Zeichen gesendet wird, das wäre dann sehr praktisch.
Michael Knoelke schrieb:> Frank M. schrieb:>> Wenn man kein Ende-Zeichen bekommt, muss man es mit einem Timeout>> machen.>> Immer, oder ?
Wenn kein Ende-Zeichen vorgesehen ist, bleibt nur noch eine
Timeout-Behandlung. Nichts anderes habe ich gesagt.
> Was wenn das Ende Zeichen nicht kommt weil es verloren geht,
Das ist doch eine ganz andere Situation. Ich habe auf die Situation
geantwortet, dass es kein Ende-Zeichen im Protokoll gibt.
Du beschreibst aber nun die Situation, dass es ein Ende-Zeichen gibt,
dieses aber verloren gehen kann. Nebelkerze?
Glücklicherweise ist die Methode des Timeouts dann trotzdem anwendbar -
mit einem Unterschied: Bei einem Protokoll ohne Ende-Zeichen bedeutet
ein Timeout die Validierung des Strings. Wenn es aber ein Ende-Zeichen
gibt, das aber verloren gegangen ist, ist keine Validierung möglich.
In diesem Fall muss die empfangene Nachricht verworfen und neu
angefordert werden.
> oder wegen> CRC Fehler die Information über die Telegrammlänge unzuverlässig ist ?
nicht validieren, verwerfen.
> Wie entscheide ich dann wann eine neuer String kommt ?
Sorry, bezieht sich Deine Frage jetzt auf ein Protokoll mit Ende-Zeichen
oder ohne? Deine Nebelkerze oben lässt da keine eindeutigen Schlüsse zu.
Jakob schrieb:> Kann auch sein das nur eine bestimmt Anzahl an> Zeichen gesendet wird, das wäre dann sehr praktisch.
Du meinst, eine bestimmte (feste) Anzahl, dann eine längere Pause, dann
wieder diese feste Anzahl usw...?
Es wird eine Frequenz über den Bus mitgeteilt.
@ npn, ja es gibt feste Pause aber ob es nun feste Anzahl an Zeichen
gibt ist die Frage.
Werde jetzt mal warten und mich dann wenn ich damit anfange melden.
Jakob schrieb:> Es wird eine Frequenz über den Bus mitgeteilt.>> @ npn, ja es gibt feste Pause aber ob es nun feste Anzahl an Zeichen> gibt ist die Frage.>> Werde jetzt mal warten und mich dann wenn ich damit anfange melden.
Wenn das Teil kommt und es im Protokoll tatsächlich ausser Timeout keine
Möglichkeit zur Synchronisation gibt, würde ich mal heftig fluchen und
mich nach einem anderen Teil umsehen.
Absichtlich und ausschliesslich per Timeout zu synchronisieren ist die
schlechteste aller Möglichkeiten und eigentlich nur mit dem Hintergrund
der Faulheit der Programmierer zu verstehen, die den Sendecode
geschrieben haben. Denn damit bürdet man dem Empfangscode eine Menge
Stolpersteine auf. Ein Protokolldesigner hat immer beides im Auge:
Sender und Empfänger. Wer auf Timeout setzt, ignoriert ganz einfach den
Empfänger.
Also bei RS485-Kommunikation ist das mit dem Time Out recht gängig. Da
geht es oft um kurze Telegramme mit Binärdaten, bei Telegramm-Längen von
4 - 8 Bytes will man nicht mit einer Codierung anfangen, die einem Werte
'freischaufelt', die dann in den Nutzdaten nicht mehr vorkommen, und als
Ende-Kennung genutzt werden können. Allerdings ist das letzte Byte meist
ein Prüf-Byte, so daß der Empfänger prüfen kann, ob das Telegramm
vollständig, und fehlerfrei ist. Bei ASCII würde ich aber auch mit einem
Ende-Zeichen arbeiten, Auswahl gibt es da ja genug. Aber wenn der Sender
gegeben, und nicht änderbar ist ...
Mit freundlichen Grüßen - Martin
Martin Schlüter schrieb:> Also bei RS485-Kommunikation ist das mit dem Time Out recht gängig. Da> geht es oft um kurze Telegramme mit Binärdaten, bei Telegramm-Längen von> 4 - 8 Bytes will man nicht mit einer Codierung anfangen, die einem Werte> 'freischaufelt', die dann in den Nutzdaten nicht mehr vorkommen, und als> Ende-Kennung genutzt werden können
auch dort wird das Timout für den Fehlerfall verwendet und nicht für die
Endeerkennung. Man kann sonst den Bus zu wenig auslasten weil man immer
Zwangspausen einhalten muss.
Und man muss auch kein wert freischaufeln, dafür kann man ein einfaches
"escapen" verwenden.
> Also bei RS485-Kommunikation ist das mit dem Time Out recht gängig
nachtrag:
dort wird aber dafür oft ein Startzeichen + Länge + CRC verwendet, dann
braucht man auch kein Endezeichen.