Reading Serial Port

Just starting out? Need help? Post your questions and find answers here.
mlwhitt
User
User
Posts: 67
Joined: Sat Jun 11, 2005 3:38 am
Location: Western Kentucky
Contact:

Reading Serial Port

Post by mlwhitt »

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.
PB and PureVision XP Registered.
www.michaelwhitt.com
DominiqueB
Enthusiast
Enthusiast
Posts: 103
Joined: Fri Apr 25, 2003 4:00 pm
Location: France

Hello

Post by DominiqueB »

Here is a library built for managing the rs232 port:

http://perso.wanadoo.fr/marc.vitry/purebasic
Dominique

Windows 10 64bits. Pure basic 32bits
mlwhitt
User
User
Posts: 67
Joined: Sat Jun 11, 2005 3:38 am
Location: Western Kentucky
Contact:

Post by mlwhitt »

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
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

[removed]
Last edited by dracflamloc on Mon Oct 17, 2005 4:32 pm, edited 1 time in total.
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post by TerryHough »

There is likely something in my code available at
http://elfecc.no-ip.info/purebasic/inde ... erialPorts
that will help you.
Baldrick
Addict
Addict
Posts: 860
Joined: Fri Jul 02, 2004 6:49 pm
Location: Australia

Post by Baldrick »

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
mlwhitt
User
User
Posts: 67
Joined: Sat Jun 11, 2005 3:38 am
Location: Western Kentucky
Contact:

Post by mlwhitt »

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.
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
Baldrick
Addict
Addict
Posts: 860
Joined: Fri Jul 02, 2004 6:49 pm
Location: Australia

Post by Baldrick »

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.
mlwhitt
User
User
Posts: 67
Joined: Sat Jun 11, 2005 3:38 am
Location: Western Kentucky
Contact:

Post by mlwhitt »

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.
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
woki
User
User
Posts: 23
Joined: Fri Apr 25, 2003 4:48 pm
Location: Germany

Post by woki »

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; 
mlwhitt
User
User
Posts: 67
Joined: Sat Jun 11, 2005 3:38 am
Location: Western Kentucky
Contact:

Post by mlwhitt »

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
Post Reply