Hallo Zusammen,
ich habe folgendes Problem, ich lese über die UART Interruptgesteuert
Zeichen ein. Nun bekomme ich Daten in einer Frame, die auch eine
variable Anzahl von Carriage Returns und Line Feeds beinhalten, wobei
die Länge des Frames auch nicht bekannt ist. Wie erkenne ich in der
Interruptroutine, dass mein Frame komplett ist? Ich habe leider keinen
Einfluss auf die Daten die gesendet werden. Teilweise ist ein Fame
komplett, wenn ein Carriage Return gesendet wird und teilweise wieder
nicht. Wie löst man das am "elegantesten"? Wie funktioniert sowas, wenn
ich z.B. 2-3 Buffer habe und bei jedem CRLF der nächste buffer aktiviert
wird und in der ISR befüllt wird? Wie erkenne ich welchen Buffer ich in
Main() abarbeiten muss? Über einen kleinen Denkanstoß wäre ich sehr
dankbar...
Schönen Gruß
Spice
...ich gehe davon aus, dass wenn ich ein CRLF bekomme, dass der Frame
auch zu Ende bzw. komplett ist. Nach dem bearbeiten des ersten buffers
wird erst entschieden, ob der nächste gepufferte String zum aktuellen
Frame gehört(e), oder aber eine neue Frame ist. Daher müsste ich
eigentlich mehrere Buffer benutzen, weiss aber nicht genau, wie das in C
am elegantesten gelöst wird.
Spice schrieb:> Über einen kleinen Denkanstoß wäre ich sehr> dankbar...
Für die Übertragung muß es ein Protokoll geben und dieses mußt Du
implementieren.
Spice schrieb:> ...ich gehe davon aus, dass wenn ich ein CRLF bekomme, dass der Frame> auch zu Ende bzw. komplett ist.
Das ist ein ganz blöder Ansatz.
Bei einem Gespräch von Mensch zu Mensch darfst Du vermuten.
Aber bei einer Datenübertragung nicht, da mußt Du wissen.
Der Sender muß sich an ein Protokoll halten und der Empfänger muß dieses
Protokoll kennen.
Peter
Protokoll ist eigentlich soweit bekannt, ich bekomme kommagetrennte
Daten, variable anzahl, teilweise ist ein CRLF ist, dann ist ein
Datensatz zu ende und Teilweise ist ein Datensatz erst beim 2ten oder
3ten CRLF zu ende und kann bearbeitet werden.
Ob ein Datensatz zu ende ist, weiss ich erst genau, wenn ich zumindest
die ersten 4Bytes vor dem ersten CRLF auswerte.
Kann man das in der ISR ohne Probleme machen, wenn die Daten mit
115200Baud reinpurzeln? Quasi nach dem ersten CRLF die ersten 4 Byte
vergleichen, wenn identisch Frame zu ende, wenn nicht weiterlesen?
Danke für die Anregungen...
Spice schrieb:> Protokoll ist eigentlich soweit bekannt
"eigentlich" klingt ja nicht schön.
Du kannst einen FIFO im Interrupt einrichten, wo alles erstmal
gespeichert wird. Und dabei ein Flag setzen, wenn der FIFO ein CRLF
enthält. Ich würd das CRLF dann gleich durch '\0' ersetzen.
Im Main wird dann dieses Flag geprüft und eine komplette Zeile abgeholt
und geparst.
Peter
Vielen Dank Peter,
>Im Main wird dann dieses Flag geprüft und eine komplette Zeile abgeholt>und geparst.
was genau meinst du mit komplette Zeile? Wenn der Flag in der ISR
gesetzt wird, dass ein CRLF erkannt wurde, werte ich dann den Teil bis
zum ersten CRLF aus, oder nehme ich dann den kompletten buffer?
Spice schrieb:> es kann ja sein, dass ich mit der bearbeitung schneller bin, als der> Frame komplett empfangen wurde?!
Dann mußt Du eben warten. Das Protokoll taugt also nichts.
Das Protokoll sollte so entwickelt werden, daß es der Empfpänger so
einfach wie möglich auswerten kann.
Z.B. es gibt eine eindeutige Zeichenkombination, die immer das
Frameende kennzeichnet.
Sowas wie, CRLF könnte es sein, muß aber nicht, ist Mist.
Sinnvoll ist auch eine Kombination für den Framebeginn und ne CRC am
Ende, damit unvollständige oder fehlerhafte Übertragungen erkannt werden
können. Bei Drahtlos ist es quasi Pflicht.
Peter
Wenn man nicht gleich das Protokoll verbessern kann (wie oben
geschildert), würde ich das so ähnlich wie bei der lexikalischen Analyse
machen. Die ISR schreibt den Stream in einen (hier: Ring-) Puffer. Punkt
- Mehr nicht.
In einem Zustandsautomat (FSM) einer (Main-)Schleife nehme ich Zeichen
für Zeichen (FIFO) aus dem Puffer (START), bis ein Kriterium für
Zeilenende erreicht ist und springe in den nächsten Zustand um die
Bedingung zu prüfen (CHECK). Wenn die Bedingung sicher zutrifft, dann
kann der String weiter verarbeitet werden (ACT). Wenn nicht, gehts
wieder nach START.
Falls notwendig, kann man zu viel gelesene Zeichen (z.B. prefetch
während CHECK) wieder in den Stream zurücklegen.
Diese Methode funktioniert in jedem Scanner/Tokenizer (lex/flex) auch so
und die FSM kann durch weitere (Sub-)Zustände schon zum Erkennen der
Terminalsymbole (token) verwendet werden.
Falls notwendig wird dann ein Parser zur weiteren Verarbeitung einer
kompletten "Zeile" nachgeschaltet.
MfG,
Andreas