COM-Port by Vertex
BlitzPlus Forums/BlitzPlus Programming/COM-Port by Vertex
| ||
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) |
| ||
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. |
| ||
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" |
| ||
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 |
| ||
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" |
| ||
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? |
| ||
The problem is that SetCommState dosn't accept 9600,N,8,1 as valid comm settings, however 9600,N,8,0 works instead. |
| ||
Very strange. I wonder why. |