Du kannst das mit WaitCommEvent machen. So wie ich es in dem
Beispiel machen, blockiert aber die Funktion. Deshalb in einem Thread.
Man kann es auch anderst machen, das ist aber aufwendiger.
Code: Alles auswählen
;PureBasic 3.94
Declare ThreadEmpf()
Global ComPort.s , hCom , ThreadID , ComEvent ,BufferRx.s , CountBuffer , ComError
Global IDWndMain , hWndMain ,StrEmpf
;Die benötigten Strukturen
Global dcb.DCB ;Einstellungen der Schnittstelle
Global ccf.COMMCONFIG
Global o.OVERLAPPED ;Damit andere Prozesse Zugriff haben. Vorletzter Parameter bei CreateFile
Global timeouts.COMMTIMEOUTS
BufferRx = Space(255); Hier schreibt ReadFile die empfangenden Daten rein
ComPort = "COM2" ;
FillMemory_(@ccf\dcb, SizeOf(dcb), 0);DCB-Struktur mit Nullen füllen
dcb\DCBlength = SizeOf(DCB); Größe der Struktur ermitteln
ccf\dwSize = SizeOf(COMMCONFIG) + dcb\DCBlength ; Größe der Struktur ermitteln
;Einstellungen aus dem Gerätemanager verwenden.
; Man kann die Struktur aber auch selbst füllen. Z.Bsp mit "BuildCommDCB", oder von Hand
GetDefaultCommConfig_(ComPort, @ccf, @ccf\dwSize)
SetDefaultCommConfig_(ComPort, @ccf, @ccf\dwSize)
;Comport öffnen.;z.Bsp Com2. Das "\\.\" ist nur für ComPortnummern über 12 erforderlich
hCom = CreateFile_("\\.\"+ComPort, #GENERIC_READ |#GENERIC_WRITE ,0,0, #OPEN_EXISTING ,#FILE_FLAG_OVERLAPPED ,0)
If hCom <> #INVALID_HANDLE_VALUE
SetCommMask_(hCom,#EV_RXCHAR );Event festlegen. Wenn ein Byte emfangen wird, wird ein Event ausgelöst
SetCommState_(hCom,@ccf\dcb) ; Einstellungen übernehmen
SetupComm_(hCom, 255,255);Empangs- und SendeBuffer einstellen
GetCommTimeouts_( hCom,@timeouts)
timeouts\ReadIntervalTimeout = #MAXWORD
timeouts\ReadTotalTimeoutMultiplier = 0
timeouts\ReadTotalTimeoutConstant = 300 ; Wartet 300ms
timeouts\WriteTotalTimeoutMultiplier = 0
timeouts\WriteTotalTimeoutConstant = 0
SetCommTimeouts_( hCom,@timeouts)
ClearCommError_(hCom,@ComError,#NULL); Löscht alle evt. Fehler
PurgeComm_(hCom,#PURGE_TXCLEAR | #PURGE_RXCLEAR);Leert die Buffer
ThreadID = CreateThread(@ThreadEmpf(),0);Thread starten
Else
MessageRequester("","ComPort kann nicht geöffnet werden")
End ;Wenn man will, Programm beenden
EndIf
;Jetzt die Threadfunktion. An dieser Stelle im Code muss sie aber declariert werden!!
Procedure ThreadEmpf()
;So wie " WaitCommEvent" hier verwendet wird , blockiert sie den Thread bis das Event eintritt. Man kann es auch anderst machen.
;Aber aufwendiger
Repeat
ClearCommError_(hCom,@ComError,#NULL)
WaitCommEvent_(hCom, @ComEvent,@o);
;Dann mit Readfile den Buffer auslesen. Der dritte Parameter gibt an, wieviele Byte gelesen werden sollen.
;ReadFile wartet dann solange bis alle Byte empfangen wurde. Geht ein Byte verloren, dann blockiert ReadFile.
;Um das zu verhinder kann man mit "SetCommTimeouts" Timeouts setzen.
;Man kann den dritten Parameter auch auf 1 setzen und in einer Schleife solange lesen bis der Speicher leer ist..
;"ClearCommError" gibt vorhandene Byte im Buffer zurück.
ReadFile_(hCom, BufferRx,4,@CountBuffer,0)
SetGadgetText(StrEmpf , BufferRx)
ForEver
EndProcedure
IDWndMain =OpenWindow(#PB_Any,0,0,380,160, #PB_Window_SystemMenu | #PB_Window_WindowCentered ,"USB zu RS232 Konvertertest")
hWndMain = WindowID(IDWndMain)
CreateGadgetList(hWndMain)
StrEmpf = StringGadget(#PB_Any,10,10,360,140,"")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_CloseWindow
If EventWindowID() = IDWndMain
SetCommMask_(hCom,0 ) ;Maske auf Null setzten
KillThread(hThread) ; Thread beenden
CloseHandle_(hThread); ThreadHandle schließen. Ob bei PB4.0 noch erforderlich ?
CloseHandle_(hCom) ; ComPort schließen.
End
EndIf
EndSelect
ForEver
End
Viel Spaß
Georg