Reading Serial Port
Reading Serial Port
I know that PureBasic doesn't natively support serial communications, but I was wondering if anyone had any sample code where they used PureBasic to access the Windows API to read from a RS-232 connection.
I have a sensor that I need to access thru the Com Port. I don't need to write to it, just read the data the sensor is sending. I do know that for this device that it may not work if I have Flow Control enabled.
If anyone can help me it will be great appreciated.
Thanks.
I have a sensor that I need to access thru the Com Port. I don't need to write to it, just read the data the sensor is sending. I do know that for this device that it may not work if I have Flow Control enabled.
If anyone can help me it will be great appreciated.
Thanks.
PB and PureVision XP Registered.
www.michaelwhitt.com
www.michaelwhitt.com
-
- Enthusiast
- Posts: 103
- Joined: Fri Apr 25, 2003 4:00 pm
- Location: France
Hello
Dominique
Windows 10 64bits. Pure basic 32bits
Windows 10 64bits. Pure basic 32bits
Thank you I will check it out. My French isn't that good so I might have to ask for some more help. But I think this will help.
PB and PureVision XP Registered.
www.michaelwhitt.com
www.michaelwhitt.com
-
- Addict
- Posts: 1648
- Joined: Mon Sep 20, 2004 3:52 pm
- Contact:
-
- Enthusiast
- Posts: 781
- Joined: Fri Apr 25, 2003 6:51 pm
- Location: NC, USA
- Contact:
There is likely something in my code available at
http://elfecc.no-ip.info/purebasic/inde ... erialPorts
that will help you.
http://elfecc.no-ip.info/purebasic/inde ... erialPorts
that will help you.
Here is a bit of code you may like to take a quick look at.
It may be a bit rough as I have pretty much cut & pasted from another app I have made. I have also placed the connection, Rx, etc stuff into procedures to hopefully make it easy for you to work out.
It was written using the MVCom lib DominiqueB posted you about earlier.
Hope this might help you just a little.
It may be a bit rough as I have pretty much cut & pasted from another app I have made. I have also placed the connection, Rx, etc stuff into procedures to hopefully make it easy for you to work out.
It was written using the MVCom lib DominiqueB posted you about earlier.
Hope this might help you just a little.

Code: Select all
;
; MVCom lib required for this code to work.
; Tested using Null modem cable configuration to defeat handshaking
; Db9 @ pc: p2-Rx to Tx on device, p5-gnd to gnd on device,p1p4p6- linked together on Db9
; hope this helps a little For you...
; Regards, Baldrick :)
#winw=500:#winh=400:#winx = 0:#winy= 0:pgmname.s="Quick Rs232 ComPort Connect / Receive"
Enumeration
#mainWindow
#Menu1
#Mexit
#Container1
#Connect
#Disconnect
#DataScreen
#StatusBar
EndEnumeration
MyConnection$="COM1:9600,N,8,1" ; set this string to reflect your desired ComPort settings
Procedure Inserteditortext(editorgadget,results$)
ProcedureReturn SendMessage_(GadgetID(editorgadget),#EM_REPLACESEL,0,results$)
EndProcedure
Procedure Connect(PortDesc$)
Connection=ComOpen(PortDesc$,0,256,256); handshake set as "none", in & out buffers work fine
If Connection<1 ; with a value of 1 in my tests
MessageRequester("Connection Fail","Please check ComPort settings & try again",16)
EndIf
ProcedureReturn Connection ; this will be comportId - 0 if fail
EndProcedure
Procedure Disconnect(Connection)
If Connection
ComClose(Connection)
Connection=0
EndIf
ProcedureReturn Connection ; 0 = successfully closed comport
EndProcedure
Procedure.s Rx(Connection)
cominput$="" ; must always give the cominput string a value else it will fail to retrieve
If Connection ; any data. - A small bug in the MVCOM lib
While ComInputBufferCount(Connection) ;if data in buffer
If ComInput(Connection,cominput$) ; retrieve data from buffer
inputconversion=Asc(cominput$) ; not sure why, but I have always had to do this
Rx$=Chr(inputconversion) ; to get correct character return ??
Debug cominput$
ProcedureReturn Rx$
EndIf
Wend
EndIf
EndProcedure
mainwin.l = OpenWindow(#mainWindow,#winx,#winy,#winw,#winh,#PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_ScreenCentered,pgmname)
If mainwin
CreateMenu(#Menu1, mainwin)
MenuTitle("&File")
MenuItem(#Mexit, "&Exit"):AddKeyboardShortcut(#mainWindow,#PB_Shortcut_Escape ,#Mexit)
CreateGadgetList(mainwin)
ContainerGadget(#Container1,10,10,10,10,#PB_Container_Flat)
ButtonGadget(#Connect,70,10,50,20,"Connect")
ButtonGadget(#Disconnect,130,10,60,20,"Disconnect")
EditorGadget(#Datascreen,10,70,80,20)
CloseGadgetList()
If CreateStatusBar(#Statusbar,mainwin)
StatusBarText(#StatusBar,0, "Not Connected: "+MyConnection$)
EndIf
EndIf
Repeat
EventId.l=WindowEvent()
timer+1:If timer>100:timer=0:Delay(1):Else:Delay(0):EndIf
Win1Width = WindowWidth():Win1Height = WindowHeight()
If win1Width<>win1WidthA Or Win1Height<>Win1HeightA
ResizeGadget(#Container1, 10, 10, win1Width-20, win1Height-55)
ResizeGadget(#DataScreen,10,40, win1Width-55,win1height-125)
win1widthA=win1width:Win1HeightA=Win1Height
EndIf
If Myconnection ; if connection is open
MyDat$=Rx(Myconnection) ;look to see if anything received
insert$=insert$+MyDat$
If MyDat$=Chr(10) ; do something with retrieved data
inserteditortext(#Datascreen,insert$); in this case when "Line feed" character, insert string
insert$="" ; into editor gadget, then reset string to""
EndIf
EndIf
If EventId=#PB_EventMenu
Select EventMenuID()
Case #MExit
quit=1
EndSelect
EndIf
If EventId=#PB_EventGadget
Select EventGadgetID()
Case #Connect
Myconnection=Connect(MyConnection$)
If Myconnection
StatusBarText(#StatusBar,0, "Connected: "+MyConnection$)
EndIf
Debug "If Connection > 0 ComPort is open - "+Str(MyConnection)
Case #Disconnect
Myconnection=Disconnect(Myconnection)
If Myconnection=0
StatusBarText(#StatusBar,0, "Not Connected: "+MyConnection$)
EndIf
Debug " If Connection = 0, comport is closed - "+Str(MyConnection)
EndSelect
EndIf
If eventid=#PB_Event_CloseWindow:quit=1:EndIf
Until quit=1
If Myconnection ; if connection is still open, then close it to be sure to free memory
Debug "Connection "+Str(Myconnection)+" still open ,now closing"
Myconnection=Disconnect(Myconnection)
Debug "Connection: "+Str(Myconnection)
Debug "You should disconnect before closing window"
EndIf
End
Baldrick,
Thanks for the example, It will tell me it's connected but I am still not getting any output but I can put a sniffer on the port and see that there is output from the sensor. Maybe I am doing something wrong. Thanks for the code, I will look further into it.
Thanks for the example, It will tell me it's connected but I am still not getting any output but I can put a sniffer on the port and see that there is output from the sensor. Maybe I am doing something wrong. Thanks for the code, I will look further into it.
Baldrick wrote:Here is a bit of code you may like to take a quick look at.
It may be a bit rough as I have pretty much cut & pasted from another app I have made. I have also placed the connection, Rx, etc stuff into procedures to hopefully make it easy for you to work out.
It was written using the MVCom lib DominiqueB posted you about earlier.
Hope this might help you just a little.![]()
Code: Select all
; ; MVCom lib required for this code to work. ; Tested using Null modem cable configuration to defeat handshaking ; Db9 @ pc: p2-Rx to Tx on device, p5-gnd to gnd on device,p1p4p6- linked together on Db9 ; hope this helps a little For you... ; Regards, Baldrick :) #winw=500:#winh=400:#winx = 0:#winy= 0:pgmname.s="Quick Rs232 ComPort Connect / Receive" Enumeration #mainWindow #Menu1 #Mexit #Container1 #Connect #Disconnect #DataScreen #StatusBar EndEnumeration MyConnection$="COM1:9600,N,8,1" ; set this string to reflect your desired ComPort settings Procedure Inserteditortext(editorgadget,results$) ProcedureReturn SendMessage_(GadgetID(editorgadget),#EM_REPLACESEL,0,results$) EndProcedure Procedure Connect(PortDesc$) Connection=ComOpen(PortDesc$,0,256,256); handshake set as "none", in & out buffers work fine If Connection<1 ; with a value of 1 in my tests MessageRequester("Connection Fail","Please check ComPort settings & try again",16) EndIf ProcedureReturn Connection ; this will be comportId - 0 if fail EndProcedure Procedure Disconnect(Connection) If Connection ComClose(Connection) Connection=0 EndIf ProcedureReturn Connection ; 0 = successfully closed comport EndProcedure Procedure.s Rx(Connection) cominput$="" ; must always give the cominput string a value else it will fail to retrieve If Connection ; any data. - A small bug in the MVCOM lib While ComInputBufferCount(Connection) ;if data in buffer If ComInput(Connection,cominput$) ; retrieve data from buffer inputconversion=Asc(cominput$) ; not sure why, but I have always had to do this Rx$=Chr(inputconversion) ; to get correct character return ?? Debug cominput$ ProcedureReturn Rx$ EndIf Wend EndIf EndProcedure mainwin.l = OpenWindow(#mainWindow,#winx,#winy,#winw,#winh,#PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_ScreenCentered,pgmname) If mainwin CreateMenu(#Menu1, mainwin) MenuTitle("&File") MenuItem(#Mexit, "&Exit"):AddKeyboardShortcut(#mainWindow,#PB_Shortcut_Escape ,#Mexit) CreateGadgetList(mainwin) ContainerGadget(#Container1,10,10,10,10,#PB_Container_Flat) ButtonGadget(#Connect,70,10,50,20,"Connect") ButtonGadget(#Disconnect,130,10,60,20,"Disconnect") EditorGadget(#Datascreen,10,70,80,20) CloseGadgetList() If CreateStatusBar(#Statusbar,mainwin) StatusBarText(#StatusBar,0, "Not Connected: "+MyConnection$) EndIf EndIf Repeat EventId.l=WindowEvent() timer+1:If timer>100:timer=0:Delay(1):Else:Delay(0):EndIf Win1Width = WindowWidth():Win1Height = WindowHeight() If win1Width<>win1WidthA Or Win1Height<>Win1HeightA ResizeGadget(#Container1, 10, 10, win1Width-20, win1Height-55) ResizeGadget(#DataScreen,10,40, win1Width-55,win1height-125) win1widthA=win1width:Win1HeightA=Win1Height EndIf If Myconnection ; if connection is open MyDat$=Rx(Myconnection) ;look to see if anything received insert$=insert$+MyDat$ If MyDat$=Chr(10) ; do something with retrieved data inserteditortext(#Datascreen,insert$); in this case when "Line feed" character, insert string insert$="" ; into editor gadget, then reset string to"" EndIf EndIf If EventId=#PB_EventMenu Select EventMenuID() Case #MExit quit=1 EndSelect EndIf If EventId=#PB_EventGadget Select EventGadgetID() Case #Connect Myconnection=Connect(MyConnection$) If Myconnection StatusBarText(#StatusBar,0, "Connected: "+MyConnection$) EndIf Debug "If Connection > 0 ComPort is open - "+Str(MyConnection) Case #Disconnect Myconnection=Disconnect(Myconnection) If Myconnection=0 StatusBarText(#StatusBar,0, "Not Connected: "+MyConnection$) EndIf Debug " If Connection = 0, comport is closed - "+Str(MyConnection) EndSelect EndIf If eventid=#PB_Event_CloseWindow:quit=1:EndIf Until quit=1 If Myconnection ; if connection is still open, then close it to be sure to free memory Debug "Connection "+Str(Myconnection)+" still open ,now closing" Myconnection=Disconnect(Myconnection) Debug "Connection: "+Str(Myconnection) Debug "You should disconnect before closing window" EndIf End
PB and PureVision XP Registered.
www.michaelwhitt.com
www.michaelwhitt.com
mlwhitt,
Hope this doesnt sound too obvious, but have you tried an emulator program such as "HyperTerminal" with your sensor?
That is how I would normally start with a project requiring Rs232 communications. When you know your device is communicating with your computer using your emulator then you straight away know that cables, etc are correct and you can start looking into your code from there.
Hope this doesnt sound too obvious, but have you tried an emulator program such as "HyperTerminal" with your sensor?
That is how I would normally start with a project requiring Rs232 communications. When you know your device is communicating with your computer using your emulator then you straight away know that cables, etc are correct and you can start looking into your code from there.
Baldrick,
Actually I have confirmed it with the bundled application, and a couple different terminal programs. It is working. It is sending the tempature correctly. So I am sure the cables and all are working correctly. Thanks for the tip though.
Actually I have confirmed it with the bundled application, and a couple different terminal programs. It is working. It is sending the tempature correctly. So I am sure the cables and all are working correctly. Thanks for the tip though.
Baldrick wrote:mlwhitt,
Hope this doesnt sound too obvious, but have you tried an emulator program such as "HyperTerminal" with your sensor?
That is how I would normally start with a project requiring Rs232 communications. When you know your device is communicating with your computer using your emulator then you straight away know that cables, etc are correct and you can start looking into your code from there.
PB and PureVision XP Registered.
www.michaelwhitt.com
www.michaelwhitt.com
Here simple code snippets to do com port with windows api calls.
Hope that helps.
Hope that helps.
Code: Select all
;r = CreateFile_("COM1:",#GENERIC_READ | GENERIC_WRITE,0,#NULL,#OPEN_EXISTING,0,#NULL)
devCB.DCB
r = OpenFile(0,"COM2:")
; use this to verify com port
If r
If GetCommState_(r,devCB)
SomeResults.s = "Baud rate = "+Str(devCB\BaudRate)+Chr(10)
SomeResults = SomeResults + "Data Bits = "+Str(devCB\ByteSize)+Chr(10)
SomeResults = SomeResults + "Parity = "+Str(devCB\Parity)+" (0-4=no,odd,even,mark,space)"+Chr(10)
SomeResults = SomeResults + "Stop Bits = "+Str(devCB\StopBits)+" (0,1,2 = 1, 1.5, 2)"+Chr(10)
MessageRequester("COM Port Test",SomeResults,0)
Else
MessageRequester("COM Port Test","Couldn't get COM port settings",0)
EndIf
Else
MessageRequester("COM Port Test","Couldn't open COM port",0)
EndIf
End
; use this to set com port
Comsettings$ ="19200,n,8,1"
retval = BuildCommDCB_(Comsettings$, devCB)
retval = SetCommState_(r, devCB)
FlushFileBuffers_(r)
; use this to read com port
Structure rx
byte1.b
byte2.b
byte3.b
EndStructure
*prx.rx = @rx
rbytes = 0 ;Bytes recived
ret = ReadFile_(r, *prx.rx, rxbytes, @rbytes, 0)
; r = handle of file to read
; *prx.rx = address of buffer that receives Data (structure for example)
; rxbytes = number of bytes to read
; @rbytes = address of number of bytes read
; close com port
ret = CloseHandle_(r)
; here the full structure of devCB.DCB (W32 programmers reference)
; perhaps you need to adjust your flow control
; typedef struct _DCB { // dcb
;
; DWORD DCBlength; // sizeof(DCB)
; DWORD BaudRate; // current baud rate
; DWORD fBinary: 1; // binary mode, no EOF check
; DWORD fParity: 1; // enable parity checking
; DWORD fOutxCtsFlow:1; // CTS output flow control
; DWORD fOutxDsrFlow:1; // DSR output flow control
; DWORD fDtrControl:2; // DTR flow control type
; DWORD fDsrSensitivity:1; // DSR sensitivity
; DWORD fTXContinueOnXoff:1; // XOFF continues Tx
;
; DWORD fOutX: 1; // XON/XOFF out flow control
; DWORD fInX: 1; // XON/XOFF in flow control
; DWORD fErrorChar: 1; // enable error replacement
; DWORD fNull: 1; // enable null stripping
; DWORD fRtsControl:2; // RTS flow control
; DWORD fAbortOnError:1; // abort reads/writes on error
; DWORD fDummy2:17; // reserved
; WORD wReserved; // not currently used
; WORD XonLim; // transmit XON threshold
;
; WORD XoffLim; // transmit XOFF threshold
; BYTE ByteSize; // number of bits/byte, 4-8
; BYTE Parity; // 0-4=no,odd,even,mark,space
; BYTE StopBits; // 0,1,2 = 1, 1.5, 2
; char XonChar; // Tx and Rx XON character
; char XoffChar; // Tx and Rx XOFF character
; char ErrorChar; // error replacement character
; char EofChar; // end of input character
; char EvtChar; // received event character
;
; WORD wReserved1; // reserved; do not use
; } DCB;
Thanks, I will check this out right now.
woki wrote:Here simple code snippets to do com port with windows api calls.
Hope that helps.
Code: Select all
;r = CreateFile_("COM1:",#GENERIC_READ | GENERIC_WRITE,0,#NULL,#OPEN_EXISTING,0,#NULL) devCB.DCB r = OpenFile(0,"COM2:") ; use this to verify com port If r If GetCommState_(r,devCB) SomeResults.s = "Baud rate = "+Str(devCB\BaudRate)+Chr(10) SomeResults = SomeResults + "Data Bits = "+Str(devCB\ByteSize)+Chr(10) SomeResults = SomeResults + "Parity = "+Str(devCB\Parity)+" (0-4=no,odd,even,mark,space)"+Chr(10) SomeResults = SomeResults + "Stop Bits = "+Str(devCB\StopBits)+" (0,1,2 = 1, 1.5, 2)"+Chr(10) MessageRequester("COM Port Test",SomeResults,0) Else MessageRequester("COM Port Test","Couldn't get COM port settings",0) EndIf Else MessageRequester("COM Port Test","Couldn't open COM port",0) EndIf End ; use this to set com port Comsettings$ ="19200,n,8,1" retval = BuildCommDCB_(Comsettings$, devCB) retval = SetCommState_(r, devCB) FlushFileBuffers_(r) ; use this to read com port Structure rx byte1.b byte2.b byte3.b EndStructure *prx.rx = @rx rbytes = 0 ;Bytes recived ret = ReadFile_(r, *prx.rx, rxbytes, @rbytes, 0) ; r = handle of file to read ; *prx.rx = address of buffer that receives Data (structure for example) ; rxbytes = number of bytes to read ; @rbytes = address of number of bytes read ; close com port ret = CloseHandle_(r) ; here the full structure of devCB.DCB (W32 programmers reference) ; perhaps you need to adjust your flow control ; typedef struct _DCB { // dcb ; ; DWORD DCBlength; // sizeof(DCB) ; DWORD BaudRate; // current baud rate ; DWORD fBinary: 1; // binary mode, no EOF check ; DWORD fParity: 1; // enable parity checking ; DWORD fOutxCtsFlow:1; // CTS output flow control ; DWORD fOutxDsrFlow:1; // DSR output flow control ; DWORD fDtrControl:2; // DTR flow control type ; DWORD fDsrSensitivity:1; // DSR sensitivity ; DWORD fTXContinueOnXoff:1; // XOFF continues Tx ; ; DWORD fOutX: 1; // XON/XOFF out flow control ; DWORD fInX: 1; // XON/XOFF in flow control ; DWORD fErrorChar: 1; // enable error replacement ; DWORD fNull: 1; // enable null stripping ; DWORD fRtsControl:2; // RTS flow control ; DWORD fAbortOnError:1; // abort reads/writes on error ; DWORD fDummy2:17; // reserved ; WORD wReserved; // not currently used ; WORD XonLim; // transmit XON threshold ; ; WORD XoffLim; // transmit XOFF threshold ; BYTE ByteSize; // number of bits/byte, 4-8 ; BYTE Parity; // 0-4=no,odd,even,mark,space ; BYTE StopBits; // 0,1,2 = 1, 1.5, 2 ; char XonChar; // Tx and Rx XON character ; char XoffChar; // Tx and Rx XOFF character ; char ErrorChar; // error replacement character ; char EofChar; // end of input character ; char EvtChar; // received event character ; ; WORD wReserved1; // reserved; do not use ; } DCB;
PB and PureVision XP Registered.
www.michaelwhitt.com
www.michaelwhitt.com