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 2  1 2      
AJ_Oldendorf

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

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 9. Feb 2016, 10:15
hEvent wird gesetzt beim Init des ComPorts:

rOverlapped.hEvent := CreateEventA (NIL, True, False, NullStr); Dann kommt das WaitCommEvent wie oben schonmal geschrieben und wenn dieses getriggert wird sieht mein Aufruf so aus:

Delphi-Quellcode:
ReadFile (MyHandle, ReceiveBuffer, 1024, ReceivedBytes, Nil); //<- ReceivedBytes ist hier 0
ReceivedBytes := SeriellComp.rOverlapped.InternalHigh; //<- ReceivedBytes ist hier 4
ResetEvent(rOverlapped.hEvent);
So wäre das ja richtig von der Reihenfolge oder?

Grüße
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
433 Beiträge
 
Delphi 12 Athens
 
#2

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 9. Feb 2016, 10:48
@Sir Rufo...
Zitat:
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.
Ich habe jetzt mal Byteweise die COM abgefragt und mir entsprechend beim Auftreten meines #10 den String zusammen gebaut. Das ist ja im Endeffekt ein Pollen der Seriellen Schnittstelle und man merkt dabei "deutlich", dass das mehr Rechenleistung benötigt.

Der bessere Weg ist auf ein bestimmtes Zeichen nur zur Triggern (WaitCommEvent) und dann die Daten auslesen.
Das Problem ist nur, dass dann bei mir nichts im Buffer steht wenn ich ReadFile nach dem WaitCommEvent aufrufe
  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
 
#3

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 9. Feb 2016, 11:23
@Sir Rufo...
Zitat:
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.
Ich habe jetzt mal Byteweise die COM abgefragt und mir entsprechend beim Auftreten meines #10 den String zusammen gebaut. Das ist ja im Endeffekt ein Pollen der Seriellen Schnittstelle und man merkt dabei "deutlich", dass das mehr Rechenleistung benötigt.

Der bessere Weg ist auf ein bestimmtes Zeichen nur zur Triggern (WaitCommEvent) und dann die Daten auslesen.
Das Problem ist nur, dass dann bei mir nichts im Buffer steht wenn ich ReadFile nach dem WaitCommEvent aufrufe
So sollst du das ja auch nicht machen

Hole dir alles was du vom ComPort kriegen kannst. Das ist ja eine Bytefolge. Diese packst du dann in einen Record
Delphi-Quellcode:
TDataBlock = record
  Data: TBytes;
  Timestamp: TDateTime;
end;
und den dann in eine Queue. Diese Queue wird dann von einem anderen Thread abgefragt und verarbeitet. Dort erfolgt dann das Untersuchen und Zerteilen der Nachrichten und wenn eine komplette Nachricht erkannt wurde, dann schickt dieser Thread die Nachricht raus bzw. reicht diese Nachricht an eine weitere Queue, wo dann ein Versender-Thread diese Queue abfragt und die Nachrichten an die Empfänger schickt.

Durch die unterschiedlichen Threads laufen Empfänger, Zerteiler und Versender völlig unabhängig voneinander und stören sich folglich nicht gegenseitig.

Das Konzept selber ist eine DataFlow-Pipeline und eine Implementierung findest du
https://github.com/gabr42/OmniThread...1_Pipeline.pas
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
Photoner

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

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 9. Feb 2016, 12:01
Readfile liefert in deiner Konstellation falsche Ergebnisse da es

entweder a) mit Overlapped wieder asynchron ist (Rücksprung bevor fertig gelesen)
oder b) mit nil beim Overlapped einfach falsche Ergebnisse liefern kann.

Du musst das Rückgabeergebnis von Readfile prüfen und wieder auf das Event warten:

Delphi-Quellcode:
if not ReadFile(MyHandle, ReceiveBuffer, 1024, nil, @rOverlapped) then
  if GetLastError()<>ERROR_IO_PENDING raise Exception.Create('COM Fehler');
case WaitForSingleObject(rOverlapped.hEvent,ATimeOutInMS) of
 ...
Ich muss nochmals auf die Quelle schlechthin, MSDN, hinweisen. Steht alles da.

ReadFile

"If hFile is opened with FILE_FLAG_OVERLAPPED, the lpOverlapped parameter must point to a valid and unique OVERLAPPED structure, otherwise the function can incorrectly report that the read operation is complete."

"lpNumberOfBytesRead [out, optional]
A pointer to the variable that receives the number of bytes read when using a synchronous hFile parameter. ReadFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results."

Unter Remarks:
"Synchronization and File Position

If hFile is opened with FILE_FLAG_OVERLAPPED, it is an asynchronous file handle; otherwise it is synchronous. The rules for using the OVERLAPPED structure are slightly different for each, as previously noted.
Note If a file or device is opened for asynchronous I/O, subsequent calls to functions such as ReadFile using that handle generally return immediately, but can also behave synchronously with respect to blocked execution. For more information see http://support.microsoft.com/kb/156932.


Considerations for working with asynchronous file handles:

ReadFile may return before the read operation is complete. In this scenario, ReadFile returns FALSE and the GetLastError function returns ERROR_IO_PENDING, which allows the calling process to continue while the system completes the read operation.
The lpOverlapped parameter must not be NULL and should be used with the following facts in mind:
Although the event specified in the OVERLAPPED structure is set and reset automatically by the system, the offset that is specified in the OVERLAPPED structure is not automatically updated.
ReadFile resets the event to a nonsignaled state when it begins the I/O operation.
The event specified in the OVERLAPPED structure is set to a signaled state when the read operation is complete; until that time, the read operation is considered pending.
Because the read operation starts at the offset that is specified in the OVERLAPPED structure, and ReadFile may return before the system-level read operation is complete (read pending), neither the offset nor any other part of the structure should be modified, freed, or reused by the application until the event is signaled (that is, the read completes).
If end-of-file (EOF) is detected during asynchronous operations, the call to GetOverlappedResult for that operation returns FALSE and GetLastError returns ERROR_HANDLE_EOF.
"
Chris
  Mit Zitat antworten Zitat
AJ_Oldendorf

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

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 9. Feb 2016, 12:11
Nil und @rOverlapped ist sicherlich ein Tippfehler oder?

if not ReadFile(MyHandle, ReceiveBuffer, 1024, nil, @rOverlapped) then
Also sollte ich es so machen?
Delphi-Quellcode:
while not Terminated do
begin
  HandleBuffer[0] := rOverlapped.hEvent;
  HandleBuffer[1] := wOverlapped.hEvent;
  Return := MsgWaitForMultipleObjects (Handles, HandleBuffer, False,
                                       2000, QS_ALLINPUT);
  if Terminated then exit;
  Case Return of
    WAIT_OBJECT_0 : begin
                       if ReadFile (MyHandle, ReceiveBuffer, 1024, ReceivedBytes, @rOverlapped) then
                       begin
                         ResetEvent(rOverlapped.hEvent);
                         rOverlapped.Offset := 0;
                         rOverlapped.OffsetHigh := 0;
                         if ReceivedBytes > 0 then
                         begin
                         end;
                       end;
...
Muss ich mal probieren aber steht dann in den ReceivedBytes nicht wieder 1024 drinne?
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
433 Beiträge
 
Delphi 12 Athens
 
#6

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 9. Feb 2016, 12:15
@Himitsu:
Zitat:
Ganz im Ernst, egal, ob du einen Zeitstempel brauchst. ReadFile liest das aus, was schon im Cache des Port ist.
Mir geht es aber nicht um einen Zeitstempel wann ich mir den String zusammen gebaut habe sondern wann dieser sozusagen an der Schnittstelle an lag.

Aller 9ms steht sozusagen ein neuer Wert am COM an. Den brauche ich mir dem genauen Zeitstempel wann er kam.
Der nächste Wert ist dann eben 9ms später. Das ist aber abhängig davon, wie schnell das Gerät sendet.
Kann auch mal 12ms oder ähnliches sein...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 9. Feb 2016, 12:21
Und den bekommst du Niemals raus.
Windows, der Treiber und vorallem dein Programm sind kein Echtzeitsystem.

Du kannst den Puffer nur schnell leeren und verarbeiten, womit du Zeitlich am Nächsten an die Empfangszeit ran kommst.
Alles unter 20 (sicherheitshalber unter 50) Millisekunden kannst du praktisch vergessen.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu ( 9. Feb 2016 um 12:24 Uhr)
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.739 Beiträge
 
Delphi 6 Enterprise
 
#8

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 9. Feb 2016, 13:19
@Himitsu:
Zitat:
Ganz im Ernst, egal, ob du einen Zeitstempel brauchst. ReadFile liest das aus, was schon im Cache des Port ist.
Mir geht es aber nicht um einen Zeitstempel wann ich mir den String zusammen gebaut habe sondern wann dieser sozusagen an der Schnittstelle an lag.
Dann mach doch genau das, was Sir Rufo geschrieben hat. Merk dir den momentanen Buffer samt Zeitstempel in einem Record und schieb das in einen Queue.

Ein anderer Thread arbeit nun den Queue ab. Untersucht den Record. Ist #10 drin den Part bis #10 samt dem ebenfalls im Record befindlichen Zeitstempel wegschreiben. Den Rest auch noch untersuchen. Immer noch ne #10 drin, das ganze wieder. Wenn nicht den Rest merken.
Nächsten Record (wenn denn schon einer im Queue ist) vornehmen. An den gemerkten Rest anhängen. Wieder nach #10 suchen. Falls gefunden mit dem neuen Zeitstempel aus dem neuen Record wegschreiben.
usw.usw.
Ralph
  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 9. Feb 2016, 12:24
Nil und @rOverlapped ist sicherlich ein Tippfehler oder?
Nein:

"lpNumberOfBytesRead [out, optional]
A pointer to the variable that receives the number of bytes read when using a synchronous hFile parameter. ReadFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results."

Wenn du mit Overlapped arbeitest, steht nichts sinnvolles in diesem Parameter.
Chris
  Mit Zitat antworten Zitat
AJ_Oldendorf

Registriert seit: 12. Jun 2009
433 Beiträge
 
Delphi 12 Athens
 
#10

AW: COM Port Daten auslesen und auf bestimmtes Char reagieren

  Alt 9. Feb 2016, 12:31
Das lässt sich aber nicht compilieren:

if ReadFile (MyHandle, ReceiveBuffer, 1024, Nil, @rOverlapped) then Kannst du mir mal bitte in meinem Beispiel Source von oben zeigen, wie du das genau meinst?


@himitsu
Das Windows kein Echtzeitsystem ist weiß ich aber wenn ich mal eine Zeitmessung in einem while not Terminated Thread mache, dann komme ich laut Messung auf 10ms
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 18:16 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz