COM-Port by Vertex

BlitzPlus Forums/BlitzPlus Programming/COM-Port by Vertex

TAS(Posted 2005) [#1]
I need to control an instrument through the com port. If I first set the com port to 9600,N,8,1 with Hyperterminal Vertex's code from the code archives works with the instrument. The problem seems to be that code below (a boiled down version of Vertex's original) doesn't actually change the Com port settings. Any suggestions to fix or a alternative to change the com port settings from Blitzplus?

driverHandle = apiCreateFile("COM1", $80000000 Or $40000000 , 0, 0, 3, 0, 0)
If driverHandle = -1 Then Stop

apiSetupComm(driverHandle, 1024, 1024)

dcb = CreateBank(28)
PokeInt dcb, 00, 28 ; sizeof(DCB)
PokeInt dcb, 04, 9600 ; baud rate

;val = 1 ; ;Binary Mode (skip Eof check)
;val = val Or 2 ;Enable parity checking
;val = val Or 48 ; DTR Flow control on
;PokeByte dcb, 08, val
PokeByte dcb, 08, 0 ;no parity

PokeByte dcb, 09, 0 ;16 RTS_CONTROL=48

PokeByte dcb, 18, 8 ; number of bits/byte, 4-8
PokeByte dcb, 19, 0 ; 0-4=no, odd, even, mark, space
PokeByte dcb, 20, 1 ; 0,1,2 = 1, 1.5, 2

apiSetCommState(driverHandle, dcb)
apiSetCommMask(driverHandle, EV_TXEMPTY)

; Get the Comm state
For i=0 To 27
PokeByte dcb,i,0
Next
PokeInt dcb, 0, 28 ; sizeof(DCB)

;Get the Comm state
apiGetCommState(driverHandle,dcb)

mx$= "handle = "+driverhandle +Chr$(13)
mx$=mx$+ "Baudrate " +PeekInt(dcb,4) +Chr$(13)
mx$=mx$+ "Databits " +PeekByte(dcb,18) +Chr$(13)
mx$=mx$+ "Parity " +PeekByte(dcb,19) +Chr$(13)
mx$=mx$+ "Stopbits " +PeekByte(dcb,20) +Chr$(13)
Notify mx$

apiCloseHandle(driverHandle)


WolRon(Posted 2005) [#2]
If you read furthur down the archive entry, you will see that Vertex's code isn't all correct.

"What is going on? The offsets for the DCB at offset 8 are bits not DWORDS."

Function openComport(comport, baudRate)

	Local dcbBaudRate, driverHandle, dcb
   
	If comport > 255 Or comport < 0 Then
		Return INVALID_HANDLE_VALUE
	EndIf
   
	Select baudRate
		Case 110
			dcbBaudRate = CBR_110
		Case 300
			dcbBaudRate = CBR_300
		Case 600
			dcbBaudRate = CBR_600
		Case 1200
			dcbBaudRate = CBR_1200
		Case 2400
			dcbBaudRate = CBR_2400
		Case 4800
			dcbBaudRate = CBR_4800
		Case 9600
			dcbBaudRate = CBR_9600
		Case 14400
			dcbBaudRate = CBR_14400
		Case 19200
			dcbBaudRate = CBR_19200
		Case 38400
			dcbBaudRate = CBR_38400
		Case 56000
			dcbBaudRate = CBR_56000
		Case 57600
			dcbBaudRate = CBR_57600
		Case 115200
			dcbBaudRate = CBR_115200
		Default
			Return INVALID_HANDLE_VALUE
	End Select
	
	driverHandle = apiCreateFile("COM"+comport, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
	If driverHandle = INVALID_HANDLE_VALUE Then
		Return INVALID_HANDLE_VALUE
	Else
		apiSetupComm(driverHandle, 1024, 1024)

		dcb = CreateBank(28)
		
		PokeInt dcb, 00, 28                         ; sizeof(DCB)
		PokeInt dcb, 04, dcbBaudRate                ; current baud rate

		val	= 1										; Binary Mode (skip Eof check)    
		If parityEnable	= True Then val = val Or 2	; Enable parity checking
		If protocol		= DTR_CONTROL Then val = val Or 48	; DTR Flow control on
		PokeByte dcb, 08, val
		
		val = 0
		If protocol = RTS_CONTROL Then val = val Or 48
		PokeByte dcb, 09, val

		PokeByte dcb, 18, dataBits					; number of bits/byte, 4-8
		PokeByte dcb, 19, parityBit					; 0-4=no, odd, even, mark, space
		PokeByte dcb, 20, stopBits					; 0,1,2 = 1, 1.5, 2

		apiSetCommState(driverHandle, dcb)
		apiSetCommMask(driverHandle, EV_TXEMPTY)

	EndIf
   
	FreeBank dcb
	Return driverHandle
	
End Function




After looking some more, it appears that you are already doing so.
Any suggestions to fix or a alternative to change the com port settings from Blitzplus?
The com settings DO change because I've used Vertexes code. I'm not sure what your code to return the com settings actually returns.


TAS(Posted 2005) [#3]
I have noticed that apiSetCommState returns 0 in my code but I haven't been able figure out why.

If Not apiSetCommState(driverHandle, dcb) Then Notify "error setcomm state"


WolRon(Posted 2005) [#4]
Here is the exact code I am using that works:
Function openComport(comport, baudRate)
   Local dcbBaudRate, driverHandle, dcb
   
   If comport > 255 Or comport < 0 Then
      Return False
   EndIf
   
   Select baudRate
      Case 110
         dcbBaudRate = CBR_110
      Case 300
         dcbBaudRate = CBR_300
      Case 600
         dcbBaudRate = CBR_600
      Case 1200
         dcbBaudRate = CBR_1200
      Case 2400
         dcbBaudRate = CBR_2400
      Case 4800
         dcbBaudRate = CBR_4800
      Case 9600
         dcbBaudRate = CBR_9600
      Case 14400
         dcbBaudRate = CBR_14400
      Case 19200
         dcbBaudRate = CBR_19200
      Case 38400
         dcbBaudRate = CBR_38400
      Case 56000
         dcbBaudRate = CBR_56000
      Case 57600
         dcbBaudRate = CBR_57600
      Case 115200
         dcbBaudRate = CBR_115200
      Default
         Return False
   End Select
   
   driverHandle = apiCreateFile("COM"+comport, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
   If driverHandle = INVALID_HANDLE_VALUE Then
      Return INVALID_HANDLE_VALUE
   Else
      apiSetupComm(driverHandle, 1024, 1024)
;      dcb = CreateBank(80)
;      PokeInt dcb, 00, 80                         ; sizeof(DCB)
;      PokeInt dcb, 04, dcbBaudRate                ; current baud rate
;      PokeInt dcb, 08, 1                          ; binary mode, no EOF check
;      If parityEnable = True Then
;         PokeInt dcb, 12, 1                       ; enable parity checking
;      Else
;         PokeInt dcb, 12, 0                       ; disable parity checking
;      EndIf
;      If protocol = 0 Then
;         PokeInt dcb, 24, DTR_CONTROL_ENABLE      ; DTR flow control type
;      Else
;         PokeInt dcb, 24, DTR_CONTROL_DISABLE     ; DTR flow control type
;      EndIf
;      PokeInt dcb, 28, False                      ; DSR sensitivity
;      If protocol = 1 Then
;         PokeInt dcb, 52, RTS_CONTROL_ENABLE      ; RTS flow control
;      Else
;         PokeInt dcb, 52, RTS_CONTROL_DISABLE     ; RTS flow control
;      EndIf
;      PokeInt  dcb, 60, 17                        ; reserved
;      PokeByte dcb, 70, dataBits                  ; number of bits/byte, 4-8
;      PokeByte dcb, 71, parityBit                 ; 0-4=no, odd, even, mark, space
;      PokeByte dcb, 72, stopBits                  ; 0,1,2 = 1, 1.5, 2
      
		dcb = CreateBank(28)
		
		PokeInt dcb, 00, 28                         ; sizeof(DCB)
		PokeInt dcb, 04, dcbBaudRate                ; current baud rate

		val	= 1										; Binary Mode (skip Eof check)    
		If parityEnable	= True Then val = val Or 2	; Enable parity checking
		If protocol		= DTR_CONTROL Then val = val Or 48	; DTR Flow control on
		PokeByte dcb, 08, val
		
		val = 0
		If protocol = RTS_CONTROL Then val = val Or 48
		PokeByte dcb, 09, val

		PokeByte dcb, 18, dataBits					; number of bits/byte, 4-8
		PokeByte dcb, 19, parityBit					; 0-4=no, odd, even, mark, space
		PokeByte dcb, 20, stopBits					; 0,1,2 = 1, 1.5, 2


      apiSetCommState(driverHandle, dcb)
      apiSetCommMask(driverHandle, EV_TXEMPTY)
   EndIf
   
   FreeBank dcb
   Return driverHandle
End Function

Function closeComport(driverHandle)
   If driverHandle = INVALID_HANDLE_VALUE Or driverHandle = 0 Then
      Return False
   Else
      Return apiCloseHandle(driverHandle)
   EndIf
End Function

Function writeComport(driverHandle, numBytes, buffer)
   Local state, temp

   If driverHandle = INVALID_HANDLE_VALUE Or driverHandle = 0 Then
      Return False
   EndIf
   
   apiEscapeCommFunction(driverHandle, SETRTS)
   
   temp = CreateBank(4)
   state = apiWriteFile(driverHandle, buffer, numBytes, temp, 0)
   
   apiEscapeCommFunction(driverHandle, CLRRTS)
   
   FreeBank temp
   Return state
End Function


open, close, and write all work for me. I also have this bit of code for reading, but I am not using it, so I don't know if it works:
Function readComport(driverHandle, bytesRead, bufferSize, buffer, tOut)
	Local comErrors, comStat
	
   If driverHandle = INVALID_HANDLE_VALUE Or driverHandle = 0 Then
      Return False
   EndIf
	
	PokeInt timeouts, 00, 0
	PokeInt timeouts, 04, 0
	PokeInt timeouts, 08, tOut
	PokeInt timeouts, 12, 0
	apiSetCommTimeouts(driverHandle, timeouts)
	
	comErrors = CreateBank(4)
	comStat   = CreateBank(10)
	apiClearCommError(driverHandle, comErrors, comStat)
	
	apiReadFile(driverHandle, buffer, bufferSize, bytesRead, 0)
	
	FreeBank comErrors
	FreeBank comStat
	Return True
End Function



WolRon(Posted 2005) [#5]
And, of course I am using these declarations in a COM-Port.decls file:

.lib "Kernel32.dll" 
apiCreateFile%(lpFileName$, dwDesiredAccess, dwShareMode, lpSecurrityAttributes, dwCreationDistribution, dwFlagsAndAttributes, hTemplateFile) : "CreateFileA" 
apiSetupComm%(hFile, dwInQueue, dwOutQueue) : "SetupComm" 
apiGetCommState%(hFile, lpDCB*) : "GetCommState" 
apiSetCommState%(hFile, lpCDB*) : "SetCommState" 
apiSetCommMask%(hFile, dwEvtMask) : "SetCommMask" 
apiCloseHandle%(hObject) : "CloseHandle" 
apiEscapeCommFunction%(hFile, dwFunc) : "EscapeCommFunction" 
apiWriteFile%(hFile, lpBuffer*, nNumberOfBytesToWrite, lpNumberOfBytesWritten*, lpOverlapped) : "WriteFile" 
apiSetCommTimeouts%(hFile, lpCommTimeouts*) : "SetCommTimeouts" 
apiClearCommError%(hFile, lpErrors*, lpStat*) : "ClearCommError" 
apiReadFile%(hFile, lpBuffer*, nNumberOfBytesToRead, lpNumberOfBytesRead*, lpOverlapped) : "ReadFile"



TAS(Posted 2005) [#6]
Thanks Wolran,

I tried your code, apiSetCommStatestill returns 0 but gets a drivehandle, Getcommstate indicates the settings don't change.

I would try apiBuildCommDCB but I would need to construct a pointer to a string. I there a way to do this in BlitzPlus?


TAS(Posted 2005) [#7]
The problem is that SetCommState dosn't accept 9600,N,8,1 as valid comm settings, however 9600,N,8,0 works instead.


WolRon(Posted 2005) [#8]
Very strange. I wonder why.