Hi
Ich finde es besser die Daten mit einen Thread zu lesen. Ausser dem kann man dann den Thread mehrmals auf rufen um mehrere Comports zu überwachen.
Dazu muss aber Threadsafe in den Options aktiviert werden.
Habe mal einen kompletten Code dafür als Ansatz geschrieben. Der Thread gibt die Daten dann erst raus wenn ein #LF$ gefunden wurde.
Mit einen Buffer von 2048 byte sollte es auch nicht zu einer blockierung der Schnittstelle führen. Auch wenn ein Delay vom 10ms als Pause eingetragen wurde wenn keine Daten anliegen.
Habe den code noch nicht mit echten Daten getestet...
Code: Alles auswählen
;- Konstanten
Enumeration ; Window ID
#Window
EndEnumeration
Enumeration ; Menu ID
#Menu
EndEnumeration
Enumeration ; MenuItem ID
#Menu_Start
#Menu_Stop
#Menu_Exit
EndEnumeration
Enumeration ; Statusbar ID
#Statusbar
EndEnumeration
Enumeration ; Gadget ID
#List
EndEnumeration
; ***************************************************************************************
; Es müssen immer alle Variablen declariert werden
EnableExplicit
; ***************************************************************************************
Structure udtThread
cmd.i
stat.i
; Comport Daten
SerialPort.i
SerialPortName$
Baud.i
Paritaet.i
Data.i
Stop.i
HandshakeModus.i
EingabePufferGroesse.i
AusgabePufferGroesse.i
EndStructure
Declare thReadComPort(*this.udtThread)
; ***************************************************************************************
Procedure UpdateWindow()
Protected x,y,dx,dy
Protected mn,st,tb
x = 0
y = 0
mn = MenuHeight()
st = StatusBarHeight(#StatusBar)
;tb = ToolBarHeight(#ToolBar)
dx = WindowWidth(#Window)
dy = WindowHeight(#Window) - mn - st - tb
ResizeGadget(#List, x, y, dx, dy)
EndProcedure
Global MutexWriteLog
MutexWriteLog = CreateMutex()
Procedure WriteLog(Info.s)
Protected temp.s
LockMutex(MutexWriteLog)
temp = FormatDate("%YYYY.%MM.%DD %HH:%II:%SS - ", Date()) + Info
AddGadgetItem(#List, -1, temp)
If CountGadgetItems(#List) > 500
RemoveGadgetItem(#List, 0)
EndIf
UnlockMutex(MutexWriteLog)
EndProcedure
;- Globale Variablen
Global exit = 0
Global object.udtThread
With object
; \SerialPort kommt von #PB_Any
\SerialPortName$ = "COM1"
\Baud = 19200
\Paritaet = #PB_SerialPort_NoParity
\Data = 8
\Stop = 1
\HandshakeModus = #PB_SerialPort_NoHandshake
\EingabePufferGroesse = 2048
\AusgabePufferGroesse = 2048
EndWith
Global hThread1
; Main in eine Procedure gekapselt
Procedure Main()
Protected style, event, window, menu, gadget, type
;- Fenster
style = #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget
If OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 400, 300, "Fenster", style)
; Menu
If CreateMenu(#Menu, WindowID(#Window))
MenuTitle("&Datei")
MenuItem(#Menu_Start, "&Start")
MenuItem(#Menu_Stop, "St&op")
MenuBar()
MenuItem(#Menu_Exit, "Be&enden")
EndIf
; Statusbar
CreateStatusBar(#Statusbar, WindowID(#Window))
; Gadgets
ListViewGadget(#List, 0,0,0,0)
; Init
hThread1 = CreateThread(@thReadComPort(), object)
WriteLog("Programm gestartet")
;-- Hauptschleife
Repeat
event = WaitWindowEvent()
Select event
Case #PB_Event_Menu ; ein Menü wurde ausgewählt
menu = EventMenu()
Select menu
Case #Menu_Exit
If object\stat = 0
Exit = 1
Else
MessageRequester("Stop", "Thread läuft noch")
EndIf
Case #Menu_Start
object\cmd = 1
Case #Menu_Stop
object\cmd = 2
EndSelect
Case #PB_Event_Gadget ; ein Gadget wurde gedrückt
gadget = EventGadget()
type = EventType()
Case #PB_Event_CloseWindow ; das Schließgadget vom Fenster wurde gedrückt
window = EventWindow()
If window = #Window
If object\stat = 0
Exit = 1
Else
MessageRequester("Stop", "Thread läuft noch")
EndIf
EndIf
Case #PB_Event_Repaint ; der Fensterinhalt wurde zerstört und muss neu gezeichnet werden (nützlich für 2D Grafik-Operationen)
Case #PB_Event_SizeWindow ; das Fenster wurde in der Größe verändert
window = EventWindow()
If window = #Window
UpdateWindow()
EndIf
Case #PB_Event_MoveWindow ; das Fenster wurde verschoben
Case #PB_Event_ActivateWindow ; das Fenster wurde aktiviert (hat den Fokus erhalten)
Case #PB_Event_SysTray ; das SysTray wurde aktiviert
EndSelect
Until Exit
object\cmd = 3
Delay(1000)
EndIf
EndProcedure : Main()
; ***************************************************************************************
Procedure thReadComPort(*this.udtThread)
Protected rcv.s, temp.s, exit.i, result.i, *buffer, pos1.i, pos2.i
With *this
exit = #False
temp = ""
*buffer = AllocateMemory(\EingabePufferGroesse)
Repeat
; Command
Select \cmd
Case 0 ; Nothing
Case 1 ; Init comport
If \stat = 0
\SerialPort = OpenSerialPort(#PB_Any, \SerialPortName$, \Baud, \Paritaet, \Data, \Stop, \HandshakeModus, \EingabePufferGroesse, \AusgabePufferGroesse)
If \SerialPort = 0
\stat = 100
Else
WriteLog("ComPort geöffnet. Warten auf Daten...")
\stat = 1
EndIf
EndIf
\cmd = 0
Case 2 ; Close comport
If \stat > 0 And \stat < 100
CloseSerialPort(\SerialPort)
WriteLog("Comport geschlossen.")
EndIf
\stat = 0
\cmd = 0
Case 3 ; Exit thread
If \stat = 0
exit = #True
EndIf
\cmd = 0
EndSelect
; Status
Select \stat
Case 0 ; Nothing
Delay(100)
Case 1 ; Wait data
result = AvailableSerialPortInput(\SerialPort)
If result
\stat = 2
Else
Delay(10)
EndIf
Case 2 ; Read data
result = ReadSerialPortData(\SerialPort, *buffer, \EingabePufferGroesse)
\stat = 3
Case 3 ; Check data
rcv = PeekS(*buffer, result)
pos1 = 1
Repeat
pos2 = FindString(rcv, #LF$, pos1)
If pos2
temp + Mid(rcv, pos1, pos2 - pos1)
WriteLog("Data - " + temp)
pos1 = pos2 + 1
temp = ""
Else
temp = Mid(rcv, pos1) ; Rest für den nächsten empfang bis LF zwichenspeichern
Break
EndIf
ForEver
\stat = 1 ; zurück zum warten auf daten
Case 100 ; Error
WriteLog("Fehler beim öffnen des Comport")
\stat = 0
EndSelect
Until exit
; Exit
FreeMemory(*buffer)
EndWith
EndProcedure
; ***************************************************************************************
; ***************************************************************************************
FF
P.S.
- Bugfix
- Habe WriteLog mal mit ein Mutex gekapselt um diesen aus verschiedenen Thread aufrufen zu können.