Ich habe für meine Mikrocontroller-Projekte dafür ein Interface gebaut für die serielle Kommunikation. Das sieht so aus:
Code: Alles auswählen
Interface Serial
open.i(device.s, baudrate.i, parity.i = #PB_SerialPort_NoParity, dataBits.i = 8, stopBit.i = 1, handShake.i = #PB_SerialPort_NoHandshake)
close.i()
sendData(*buffer, length.i)
sendChar(char.a)
sendFloat(float.f)
receiveData(*buffer, length.i)
receiveChar.a()
receiveLong.l()
sendUnicode(unicode.u)
receiveUnicode.u()
receiveFloat.f()
sendString(string.s) ; Sendet den String ohne Nullbyte am Schluss
receiveString.s(length.i = -1, eol.c = 0)
availableData.i()
waitFor.i(*buffer, length.i)
isOpen.i()
lock()
unlock()
tryLock.i()
free()
bps.f()
availableOutput.i()
EndInterface
Structure SerialS
vTable.i
device.s
baudrate.i
handle.i
hMutex.i
lastTime.i
bytesSent.i
EndStructure
Procedure.i Serial_new()
Protected *this.SerialS
*this = AllocateMemory(SizeOf(SerialS))
If Not *this : ProcedureReturn #False : EndIf
*this\vTable = ?vTable_Serial
*this\hMutex = CreateMutex()
*this\bytesSent = 0
ProcedureReturn *this
EndProcedure
Procedure.i Serial_open(*this.SerialS, device.s, baudrate.i, parity.i = #PB_SerialPort_NoParity, dataBits.i = 8, stopBit.i = 1, handShake.i = #PB_SerialPort_NoHandshake)
If IsSerialPort(*this\handle)
CloseSerialPort(*this\handle)
EndIf
*this\handle = OpenSerialPort(#PB_Any, device, baudrate, parity, dataBits, stopBit, handShake, 4096, 4096)
If Not *this\handle : ProcedureReturn #False : EndIf
*this\device = device
*this\baudrate = baudrate
ProcedureReturn #True
EndProcedure
OpenSerialPort(#PB_Any, "/dev/rfcomm0", 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 4096, 4096)
Procedure Serial_close(*this.SerialS)
If IsSerialPort(*this\handle)
CloseSerialPort(*this\handle)
EndIf
EndProcedure
Procedure Serial_sendData(*this.SerialS, *buffer, length.i)
Protected pos.i = 0
If IsSerialPort(*this\handle)
While pos < length
pos + WriteSerialPortData(*this\handle, *buffer + pos, length - pos)
Wend
*this\bytesSent + length
EndIf
EndProcedure
Procedure Serial_sendChar(*this.SerialS, char.a)
Protected pos.i = 0
If IsSerialPort(*this\handle)
While pos < 1
pos + WriteSerialPortData(*this\handle, @char, 1)
Wend
*this\bytesSent + 1
EndIf
EndProcedure
Procedure Serial_sendFloat(*this.Serial, float.f)
*this\sendData(@float, SizeOf(Float))
EndProcedure
Procedure Serial_receiveData(*this.SerialS, *buffer, length.i)
Protected pos.i = 0
If IsSerialPort(*this\handle)
While pos < length
pos + ReadSerialPortData(*this\handle, *buffer + pos, length - pos)
Wend
ProcedureReturn length
EndIf
ProcedureReturn #False
EndProcedure
Macro Serial_receiveTYPE(__name, __t, __s, __return)
Procedure.__s Serial_receive#__name(*this.Serial)
Protected result.__s
If (*this\receiveData(@result, SizeOf(__t)))
ProcedureReturn result
EndIf
ProcedureReturn __return
EndProcedure
EndMacro
Serial_receiveTYPE(Char, Character, c, 0)
Serial_receiveTYPE(Long, Long, l, 0)
Serial_receiveTYPE(Unicode, Unicode, u, 0)
Serial_receiveTYPE(Float, Float, f, 0.0)
Procedure Serial_sendUnicode(*this.SerialS, unicode.u)
Protected pos.i = 0
If IsSerialPort(*this\handle)
While pos < 2
pos + WriteSerialPortData(*this\handle, @unicode + 1 - pos, 2 - pos)
Wend
*this\bytesSent + 2
EndIf
EndProcedure
Procedure Serial_sendString(*this.SerialS, string.s)
Protected pos.i, length.i = Len(string)
If IsSerialPort(*this\handle)
While pos < length
pos + WriteSerialPortData(*this\handle, @string + pos, length - pos)
Wend
*this\bytesSent + length
EndIf
EndProcedure
Procedure.s Serial_receiveString(*this.SerialS, length.i = -1, eol.c = 0)
Protected pos.i = 0, *mem, result.s = "", c.a
If IsSerialPort(*this\handle)
If length = 0 : ProcedureReturn "" : EndIf
While length
While Not ReadSerialPortData(*this\handle, @c, 1) : Wend
If (Not c) Or (c = eol) : Break : EndIf
result + Chr(c)
length - 1
Wend
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Serial_availableData(*this.SerialS)
If IsSerialPort(*this\handle)
ProcedureReturn AvailableSerialPortInput(*this\handle)
EndIf
ProcedureReturn 0
EndProcedure
Procedure.i Serial_waitFor(*this.SerialS, *buffer.Ascii, length.i)
Protected try.i = 0
If IsSerialPort(*this\handle)
Protected i.i = 0, Dim copyBuffer.a(length - 1), j.i = 0, full.i = 1
Repeat
While Not ReadSerialPortData(*this\handle, @copyBuffer(j), 1) : Wend
j = (j + 1) % length
If (full < length)
full + 1
Else
For i = 0 To length - 1
If (*buffer\a <> copyBuffer((j + i) % length))
*buffer - i
try + 1
Break
EndIf
*buffer + 1
Next
If (i = length)
Break
EndIf
EndIf
ForEver
EndIf
ProcedureReturn #True
EndProcedure
Procedure.i Serial_isOpen(*this.SerialS)
ProcedureReturn IsSerialPort(*this\handle)
EndProcedure
Procedure Serial_lock(*this.SerialS)
LockMutex(*this\hMutex)
EndProcedure
Procedure Serial_unlock(*this.SerialS)
UnlockMutex(*this\hMutex)
EndProcedure
Procedure.i Serial_tryLock(*this.SerialS)
ProcedureReturn TryLockMutex(*this\hMutex)
EndProcedure
Procedure Serial_free(*this.SerialS)
FreeMutex(*this\hMutex)
FreeMemory(*this)
EndProcedure
Procedure.f Serial_bps(*this.SerialS)
Protected newTime.i = ElapsedMilliseconds()
Protected bps.f = *this\bytesSent / ((newTime - *this\lastTime) / 1000.0)
*this\lastTime = newTime
*this\bytesSent = 0
ProcedureReturn bps
EndProcedure
Procedure.i Serial_availableOutput(*this.SerialS)
If IsSerialPort(*this\handle)
ProcedureReturn AvailableSerialPortOutput(*this\handle)
EndIf
ProcedureReturn -1
EndProcedure
DataSection
vTable_Serial:
Data.i @Serial_open(), @Serial_close(), @Serial_sendData(), @Serial_sendChar(), @Serial_sendFloat()
Data.i @Serial_receiveData(), @Serial_receiveChar(), @Serial_receiveLong()
Data.i @Serial_sendUnicode(), @Serial_receiveUniCode()
Data.i @Serial_receiveFloat()
Data.i @Serial_sendString(), @Serial_receiveString(), @Serial_availableData(), @Serial_waitFor()
Data.i @Serial_isOpen(), @Serial_lock(), @Serial_unlock(), @Serial_tryLock(), @Serial_free()
Data.i @Serial_bps(), @Serial_availableOutput()
EndDataSection
Wenn ich mal mehr Zeit finde, kommentiere ich es noch ausführlicher und stelle es in "Codes, Tipps & Tricks" ein. Außerdem wäre wohl eine Kapselung in ein Modul auch noch etwas schöner.