AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi COM Port Daten auslesen und auf bestimmtes Char reagieren
Thema durchsuchen
Ansicht
Themen-Optionen

COM Port Daten auslesen und auf bestimmtes Char reagieren

Ein Thema von AJ_Oldendorf · begonnen am 8. Feb 2016 · letzter Beitrag vom 11. Feb 2016
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
AJ_Oldendorf

Registriert seit: 12. Jun 2009
385 Beiträge
 
Delphi 12 Athens
 
#1

COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 13:50
Hallo zusammen,
ich habe ein Gerät, welches mir ca. aller 10ms ein Wert über die serielle Schnittstelle liefert.
Dieser String hat immer den gleichen Aufbau und endet mit #13#10.
Das Gerät kann aber auch andere Daten schicken aber es wird immer mit #13#10 abgeschlossen.
In meiner Software habe ich eingestellt, dass ich auf das #10 reagieren möchte und damit das Ende eines Strings erkenne.
Leider wird mir immer der komplette Buffer gefüllt den ich bei ReadFile angegeben habe und nicht nur bis zu dem gesetztem RXFlagChar (#10).

Zum seriellen Gerät:
Baudrate: 19200
Parität: Keine
StopBits: 1

Hier ein Ausschnitt, wie ich die serielle Schnittstelle initialisiere:

Delphi-Quellcode:
  MyHandle := CreateFileA (tmpStr, Generic_Read or Generic_Write, 0, Nil,
                           Open_Existing, FILE_FLAG_OVERLAPPED, 0);
  if MyHandle <> INVALID_HANDLE_VALUE then
  begin
    if SetupComm (MyHandle, 1024, 1024) then //eigentlich interessiert mich der Buffer nicht da ich immer nur bis #10 erkennen möchte
    begin
      FillChar (DCB, SizeOf(TDCB), 0);
      DCB.DCBlength := SizeOf (TDCB);
      DCB.BaudRate := 19200;
      DCB.Flags := $0001;
      DCB.Parity := 0;
      DCB.ByteSize := ByteSize;
      DCB.StopBits := 0;
      DCB.EvtChar := #10;
      if SetCommState (MyHandle, DCB) then
      begin
        With CommTimeOuts do
        begin
          ReadIntervalTimeout := 10;
          ReadTotalTimeoutMultiplier := 0;
          ReadTotalTimeoutConstant := 0;
          WriteTotalTimeoutMultiplier := 0;
          WriteTotalTimeoutConstant := 0;
        end;
        if SetCommTimeouts(SerHandle, CommTimeOuts) then
        begin
          if SetCommMask(SerHandle, EV_RXFLAG) then
....
Die Software läuft soweit und die Kommunikation zum seriellen Gerät ist auch vorhanden nur habe ich wie gesagt das Problem, dass immer der komplette Buffer gefüllt wird, bevor ich ein Event bekomme. Ich hätte gerne ein Event nach jedem #10.

Hier der Ausschnitt vom ReadFile:

Delphi-Quellcode:
rOverlapped.Offset := 0;
rOverlapped.OffsetHigh := 0;
ReadFile (MyHandle, ReceiveBuffer, 1024, ReceivedBytes, @rOverlapped);
Kann mir da jemand ein Tip geben wo ich weiter suchen könnte?

Viele Grüße
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 14:47
Lies mal, was SetCommState zum EvtChar sagt. https://msdn.microsoft.com/en-us/lib.../aa363214.aspx

Das steuert nicht was du aussliest.
Mit ReadFile liest man immer so viel aus, wie man angibt.
Willst du das nicht, mußt du Char-Weise auslesen, oder einen Puffer/Zwischenspeicher verwenden.

MSDN-Library durchsuchenWaitCommEvent
$2B or not $2B

Geändert von himitsu ( 8. Feb 2016 um 14:50 Uhr)
  Mit Zitat antworten Zitat
Photoner

Registriert seit: 6. Dez 2012
Ort: Nürnberg
103 Beiträge
 
Delphi 10.1 Berlin Starter
 
#3

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 14:51
Wie wäre es mit dem lesen von jeweils einem Char? (wie himitsu´s Vorschlag)

 DCB.EvtChar := #0; Beispiel:

Delphi-Quellcode:

function ReadChar(var MyChar : Char) : boolean;
var
  Buffer : array[0..1] of char;
  nReadChars : dword;

begin

  if not ReadFile (   MyHandle,
         Buffer,
         1,
         nReadChars,
         nil) then begin
    result := false;
    exit;
  end;

  if nReadChars = 0 then
    result := false
  else begin
    result := true;
    MyByte := Buffer[0];
  end;

end;

function GetAnswer(const ATimeOutInMS : Cardinal) : String;
var
 i : Integer;
 TimeStamp : Cardinal;
 AnswerChars : Array of Char;
 CurrentChar : Char;
begin
 TimeStamp := GetTickCount;
 Result := '';
 while True do begin
  if ReadChar(CurrentChar) then begin
   // #13#10 beendet gültige Antwort:
   if CurrentChar=#13 then break;
   SetLength(AnswerChars,Length(AnswerChars)+1);
   AnswerChars[High(AnswerChars)] := CurrentChar;
  end;
  if GetTickCount>TimeStamp+ATimeOutInMS then begin
   //Result := 'Timeout beim Lesen';
   exit;
  end;
 end;
 SetLength(Result,Length(AnswerChars));
 for i:= 1 to Length(AnswerChars) do Result[i] := AnswerChars[i];
end

Verknüpft mit einem "ATimeOutInMS" von 9 (ms) sollte das deinen Zwecken genügen.

Evtl. ist noch was falsch im Code. Nur im Browser getippt; er ist nicht getestet.
Chris

Geändert von Photoner ( 8. Feb 2016 um 14:53 Uhr) Grund: CurrentChar<>#13 stand ursprünglich da, was falsch ist
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
385 Beiträge
 
Delphi 12 Athens
 
#4

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 14:57
Ok, Zeichenweise auslesen wäre auch noch möglich aber ich dachte das "EvtChar" ist genau dafür da.
Da steht ja:
The value of the character used to signal an event.

Ich bin davon ausgegangen, dass ich ein Event bekomme wenn das entsprechende Char gefunden wurde im Buffer...

Das andere muss ich mir mal genauer angucken von "Photoner"
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
385 Beiträge
 
Delphi 12 Athens
 
#5

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 15:18
Habe anstatt dem ReadFile folgenden Aufruf gemacht:

Delphi-Quellcode:
TmpMask := EV_RXFLAG;
WaitCommEvent(MyHandle, TmpMask, @rOverlapped);
Darauf wird auf alle Fälle reagiert aber wie komme ich jetzt an die Daten? Nach dem ReadFile stehen die Daten ja in dem übergebenen ReceiveBuffer.
  Mit Zitat antworten Zitat
Neumann

Registriert seit: 6. Feb 2006
Ort: Moers
536 Beiträge
 
Delphi 12 Athens
 
#6

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 15:20
Warum die Comport-Geschichte selber bauen wenn es sie schon fertig gibt?

Komponente TComport Dejan Crnila, kann man mit allen Delphi-Versionen einsetzen und läuft bei mir einwandfrei.
Ralf
Gruß vom Niederrhein
  Mit Zitat antworten Zitat
Photoner

Registriert seit: 6. Dez 2012
Ort: Nürnberg
103 Beiträge
 
Delphi 10.1 Berlin Starter
 
#7

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 15:25
Habe anstatt dem ReadFile folgenden Aufruf gemacht:

Darauf wird auf alle Fälle reagiert aber wie komme ich jetzt an die Daten? Nach dem ReadFile stehen die Daten ja in dem übergebenen ReceiveBuffer.
Du sagst es doch selber. Mach den ReceiveBuffer im ReadFile groß genug und gehe die einzelnen Chars dann durch bis du auf das #13#10 triffst. Alles davor ergibt dir deinen String. Dein Event signalisiert dir doch jetzt ob #10 im Buffer ist
(Zitat MSDN :
"EV_RXFLAG
0x0002
The event character was received and placed in the input buffer. The event character is specified in the device's DCB structure, which is applied to a serial port by using the SetCommState function."
)
Chris
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
385 Beiträge
 
Delphi 12 Athens
 
#8

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 15:46
Folgendes habe ich vergessen zu sagen:
Ich brauche zu jedem Wert den ich übermittelt bekommen habe sozusagen ein Zeitstempel wann der Wert eingetroffen ist.
Wenn ich jetzt den Buffer sehr groß stelle, dann werden intern "ganz viele" Werte aufgesammelt. Anschließend soll ich die ja einzeln abgrasen und auf das bestimmte Ev_Char prüfen.
Ich will ja keine Verzögerung zwischen dem Eingang des Strings und der Weitergabe habe (also kein Buffer von x Strings).

Und die Länge vor dem #10 ist auch unterschiedlich. Ein String vor dem #10 kann mal 16 Bytes lang sein, mal aber auch nur 4 Byte oder 18 Bytes...

Geändert von AJ_Oldendorf ( 8. Feb 2016 um 16:03 Uhr)
  Mit Zitat antworten Zitat
Photoner

Registriert seit: 6. Dez 2012
Ort: Nürnberg
103 Beiträge
 
Delphi 10.1 Berlin Starter
 
#9

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 16:32
Bin beim lesen darauf gestoßen:

Zitat MSDN:
------------------------------------------------------------------------------------------------------------------------------
ReadIntervalTimeout

The maximum time allowed to elapse before the arrival of the next byte on the communications line, in milliseconds. If the interval between the arrival of any two bytes exceeds this amount, the ReadFile operation is completed and any buffered data is returned. A value of zero indicates that interval time-outs are not used.

A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier members, specifies that the read operation is to return immediately with the bytes that have already been received, even if no bytes have been received.

------------------------------------------------------------------------------------------------------------------------------

Setz das und lese als Reaktion auf dein Event.

Dein Event "#10 Empfangen" wird gefeuert --> du hast einen kompletten String im Buffer und einen ziemlich exakten Zeitstempel.

Readfile blockiert mit der oben erwähnten Einstellung nicht (Zeitstempel hier ist also auch ok) und kommt sofort zurück (Wenn du 1024 bytes anforderst bekommst du trotzdem nur das was im Buffer -Stichwort ReceivedBytes- ist)

Zufrieden ?
Chris
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 8. Feb 2016, 16:36
Also ich würde so etwas immer aufteilen.

Eine Klasse holt Bytefolgen vom ComPort ab und gibt diese mit dem Zeitstempel weiter.

Eine Klasse nimmt die Bytefolge/Zeitstempel Nachricht und baut bei jedem Vorkommen von #13#10 eine Nachricht mit Bytefolge/Zeitstempel und gibt diese weiter.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:57 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