Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   TComPort 4.0, OnRXChar, Zeile erkennen (https://www.delphipraxis.net/155694-tcomport-4-0-onrxchar-zeile-erkennen.html)

schwa226 4. Nov 2010 07:58

TComPort 4.0, OnRXChar, Zeile erkennen
 
Hi,

ich stehe vor einem blöden Problem.
Ich benutze die TComPort Komponente um mit der RS232 Daten zu empfangen.
Diese Daten werden im Ereigniss OnRxChar in einem Richedit als Text hinzugefügt.

Je nachdem, wie lange der PC/delphi braucht kommt über OnRxChar das nächste Teilstück von Daten daher. Auch kommen in den Daten die Zeilenumbrüche mit.

Nun kann es aber sein, dass beim ersten OnRxChar noch kein Zeilenumbruch dabei war und dieser erst beim zweiten OnRxChar ankommt.

Also ca. so:
1. 28wa98ap#$D#$As28ra0
2. 0a00np#$D#$As28wa88
3. ap#$D#$A....

Komplett zusammengefügt schaut es natürlich OK aus:
Code:
28wa98ap
s28ra00a00np
s28wa88ap
s28ra00a00np
s20wap
s21wap
s3Cwap
s50wap
Nun möchte ich jede Zeile "Übersetzen". z.B. s28r wird zu Device 0x28, Read usw.
Dieses Übersetzen macht natürlich nur Sinn, wenn die Zeile komplett ist.

Nun Frage ich mich wie ich das machen kann, damit ich "live" die Daten übersetzen kann. Aber natürlich nur wenn die Line volständig ist.

Gibt es sowas wie ein Event "On new line" in einem Memo/Richedit/...
Oder wie könnte man das lösen?

Danke!

soulies 4. Nov 2010 08:05

AW: TComPort 4.0, OnRXChar, Zeile erkennen
 
Hoi,

so weit ich mich erinnern kann ist "#0" das Zeilenende / Datenende bei RS232.
Lies doch solange ein bis das Zeichen angekommen ist, dann ist deine zeile komplett.

cya

himitsu 4. Nov 2010 08:13

AW: TComPort 4.0, OnRXChar, Zeile erkennen
 
Schreibe im OnRXChar erstmal alles in einen Puffer-String (immer schön alles hinten anhängen),
dann schaust du am Ende von OnRXChar, ob ein Zeilenumbruch vorhanden ist,
nimmst alles vor diesem Zeilenumbruch raus (und inkl. Zeilenumbruch aus dem Puffer löschen), interpretierst/übersetzt es und zeigst es an.
Das wiederholen, bis kein Zeilenumbruch mehr erkannt wird.
Der Rest verbleibt im Puffer-String, bis weitere Daten eintreffen oder bis die Verbindung getrennt wird.
Tja, nun wartest du halt bis zu den nächsten Daten oder auf das Ende und beginnst von vorne.

schwa226 4. Nov 2010 08:29

AW: TComPort 4.0, OnRXChar, Zeile erkennen
 
Ein #0 habe ich leider nicht dabei.

Ok,
dann werde ich mir mal einen Buffer bauen.

Hatte gehofft, dass es dazu schon etwas einfacheres gäbe... ;)

LargoD 4. Nov 2010 09:05

AW: TComPort 4.0, OnRXChar, Zeile erkennen
 
Schau Dir mal die Paket-Erkennung in TComPort von Dejan Crnilla an.
Da ist alles drin was Du brauchst. Das OnPaket Event wird erst ausgelöst, wenn die gewünschte Zeichenkombination gefunden wurde, in Deinem Fall also #$0d#$0a.

Gruß
Erich

schwa226 4. Nov 2010 09:14

AW: TComPort 4.0, OnRXChar, Zeile erkennen
 
Werde ich mir noch ansehen!

Zur Zeit habe ich es so gelöst:
Delphi-Quellcode:
function TForm1.SplitBuffer(Value: String; var Data : TStringList): String;
var
  i : Integer;
begin
  Result := Value;

  while Pos(#$D#$A, Result) <> 0 do
  begin
    i := Pos(#$D#$A, Result);
    Data.Add(LeftStr(Result, i - 1));
    Result := RightStr(Result, Length(Result) - i - 5);
  end;
end;
Delphi-Quellcode:
procedure TForm1.OnRxChar(Sender: TObject; Count: Integer);
var
  ReceivedData : AnsiString;
  i, count : Integer;
begin
  ComPort_Connection.ReadStr(ReceivedData, count);

  TextBuffer := TextBuffer + ReceivedData;

  NewLines.Clear;
  TextBuffer := SplitBuffer(TextBuffer, NewLines);
  // Analyse NewLines here...
end;

himitsu 4. Nov 2010 13:00

AW: TComPort 4.0, OnRXChar, Zeile erkennen
 
Bei dem "Count" scheint was nicht zu stimmen, denn dieses hast du grade doppelt ... als Parameter und als lokale Variable (aber hier sollte Delphi ja mecker)

ansonsten ... wozu doppelt suchen:
Delphi-Quellcode:
procedure TForm1.SplitBuffer(var Value: String; Data: TStringList);
var
  i : Integer;
begin
  while true do
  begin
    i := Pos(#$D#$A, Value);
    if i = 0 then exit;
    Data.Add(LeftStr(Value, i - 1)); // Data.Add(Copy(Value, 1, i - 1));
    Delete(Value, i + 1);
  end;
end;

procedure TForm1.OnRxChar(Sender: TObject; Count: Integer);
var
  ReceivedData : AnsiString;
  i: Integer;
begin
  ComPort_Connection.ReadStr(ReceivedData, Count);

  TextBuffer := TextBuffer + ReceivedData;

  NewLines.Clear;
  SplitBuffer(TextBuffer, NewLines);
  // Analyse NewLines here...
end;
und notfalls kann man es auch direkt in der Schleife verarbeiten und sich so die StringList sparen:
Delphi-Quellcode:
procedure TForm1.OnRxChar(Sender: TObject; Count: Integer);
var
  ReceivedData : AnsiString;
  i: Integer;
begin
  ComPort_Connection.ReadStr(ReceivedData, Count);
  TextBuffer := TextBuffer + ReceivedData;
  while true do
  begin
    i := Pos(#$D#$A, TextBuffer);
    if i = 0 then break;
    Value := LeftStr(TextBuffer, i - 1); // Value := Copy(TextBuffer, 1, i - 1);

    // Analyse Value here...

  end;
end;
und beim Trennen der Verbindung, dann noch den Rest verarbeiten
Delphi-Quellcode:
if TextBuffer <> '' then
begin
  // Analyse TextBuffer here...
end;

schwa226 9. Nov 2010 06:30

AW: TComPort 4.0, OnRXChar, Zeile erkennen
 
Danke für die Verbesserungen!

Werde ich dann mal testen.

Jetzt habe ich noch aber eine andere Frage zu diesem Thema!
Über die OnRxChar kommen laufen neue Daten rein. Und das nicht wenig (Baud=230400).

Jetzt habe ich das Problem, wenn ich die Stringbearbeitung in der OnRxChar drinnen habe das mir anscheinend der COM-Port/Buffer geblockt wird und mir Daten verloren gehen. Das RS232 Device ist nur über die TX Leitung verbunden. Also nichts mit Handshake usw. Die String-Bearbeitung ist dann auch noch um einiges größer.

Wenn ich nur die Daten auslese per ComPort_Connection.ReadStr(ReceivedData, Count) und dann einfach in ein Memo einfüge geht es ohne Probleme.

Gibt es da eine leichte Möglichkeit die Daten wohin zu schaufeln, damit der COM-Port nicht gebremst wird?
Meine Idee wäre ein Thread, denn ich dauernd die ReceivedData zugebe. Die String Verarbeitung erfolgt dann erst im Thread und dieser Synchronisiert sich dann mit einen Memo für die Ausgabe.
Damit sollte der Hauptthread dann nicht blockiert werden.

Kann der Hauptthread den Thread per Property eigentlich laufend Daten übergeben oder muss dazu der Thread pausiert werden? Rückwerts Thread->Hauptthread geht ja über Synchronize.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:16 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz