I found a serial port monitor in the old forum posted by Redskull in 2006, and it fails to build due to not recognizing the DCB BITRECORD structure.
http://www.masmforum.com/board/index.php?topic=5972.0
Quote
.486
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
.data
szFrameError db "!" ; Display character for errors
displaystring1 db "Monitoring for Data:",0 ; Output display string
.data?
hSerialPort DWORD ? ; handle for serial port
SerialSettings DCB {?} ; settings for serial port
SerialTimeOuts COMMTIMEOUTS {?} ; timeout settings for serial port
NumberOfBytesRead DWORD ? ; rcv variable for bytes read from ReadFile
EvtMask DWORD ? ; rcv variable for comm event returned
SerialError DWORD ? ; holder for error occured
RcvBuffer DWORD ? ; variable for holding input to go to screen
hConsoleOutput DWORD ? ; Handle to the display console
ConsoleWriteBytes DWORD ? ; rcv variable for bytes written to console
.const
Comm1 db "COM1:", 0 ; Comm port constants
Comm2 db "COM2:", 0
Comm3 db "COM3:", 0
.code
start:
;-----------------------------
; Allocate a console for displaying output
;-----------------------------
invoke AllocConsole
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hConsoleOutput, eax
; do not process control codes, display thier hex equivalents
invoke SetConsoleMode, hConsoleOutput, ENABLE_WRAP_AT_EOL_OUTPUT
;-----------------------------
; Serial Port initialization
;-----------------------------
invoke CreateFile, ADDR Comm1, GENERIC_READ OR\ ; Open the Serial Port
GENERIC_WRITE,0, NULL, OPEN_EXISTING,0,NULL
mov hSerialPort, eax ; save the handle
mov SerialSettings.DCBlength, SIZEOF DCB ; configure the Settings variable
invoke GetCommState, hSerialPort, ADDR SerialSettings ; fill it with the current settings
mov SerialSettings.BaudRate, CBR_19200 ; Baud Rate
mov SerialSettings.ByteSize, 8 ; Data Bits: 8
mov SerialSettings.Parity, NOPARITY ; Parity: None
mov SerialSettings.StopBits, ONESTOPBIT ; Stop Bits: 1
mov SerialSettings.fOutxCtsFlow, FALSE ; No RTS
mov SerialSettings.fRtsControl, RTS_CONTROL_DISABLE ; No CTS
mov SerialSettings.fOutxDsrFlow, FALSE ; No DSR TX inhibiting
mov SerialSettings.fDsrSensitivity, FALSE ; No DSR RX inhibiting
mov SerialSettings.fDtrControl, DTR_CONTROL_ENABLE ; Enable DTR Signal
mov SerialSettings.fOutX, TRUE ; xOn/xOff enabled for TX
mov SerialSettings.fInX, FALSE ; Suspend Xon/Xoff for RCV
mov SerialSettings.fNull, TRUE ; Discard NULL bytes
mov SerialSettings.fAbortOnError, FALSE ; Do not Abort on Error
mov SerialSettings.fBinary, TRUE ; Binary Transfer
mov SerialSettings.fParity, TRUE ; Parity Enabled
invoke SetCommState, hSerialPort, ADDR SerialSettings ; Apply the new settinsg
; Set the Time-outs to occur immedietly with everything in the buffer
invoke GetCommTimeouts, hSerialPort, ADDR SerialTimeOuts
mov SerialTimeOuts.ReadIntervalTimeout, MAXDWORD
mov SerialTimeOuts.ReadTotalTimeoutMultiplier, 0
mov SerialTimeOuts.ReadTotalTimeoutConstant, 0
mov SerialTimeOuts.WriteTotalTimeoutMultiplier, 0
mov SerialTimeOuts.WriteTotalTimeoutConstant, 0
invoke SetCommTimeouts, hSerialPort, ADDR SerialTimeOuts
;Generate events for received bytes and errors
invoke SetCommMask, hSerialPort, (EV_RXCHAR OR EV_ERR)
;------------------------------------------------------
invoke WriteConsole, hConsoleOutput, ADDR displaystring1, \ ; display a prompt
SIZEOF displaystring1, ADDR NumberOfBytesRead, NULL
;-----------------------------
; Poll the serial port for RCV data
;-----------------------------
.WHILE TRUE ; Enter an endless loop
invoke WaitCommEvent, hSerialPort, ADDR EvtMask, NULL ; Hold up for either a character or an error
.IF EvtMask == EV_ERR ; If an error came in...
invoke SetConsoleTextAttribute, hConsoleOutput,\ ; change to a red font
FOREGROUND_RED
invoke WriteConsole, hConsoleOutput, ADDR szFrameError,\ ; print an exclamation point
SIZEOF szFrameError, ADDR ConsoleWriteBytes, NULL
invoke SetConsoleTextAttribute, hConsoleOutput,\ ; change back to white font
FOREGROUND_BLUE OR FOREGROUND_GREEN OR FOREGROUND_RED
invoke ClearCommError, hSerialPort, ADDR SerialError, NULL; clear the error
.ENDIF
.IF EvtMask == EV_RXCHAR ; if a chracter was recieved...
.WHILE TRUE ; start a loop to empty out the serial port
invoke ReadFile, hSerialPort, RcvBuffer, SIZEOF\ ; Read in one DWORD from the serial port
RcvBuffer, ADDR NumberOfBytesRead, NULL
.BREAK .IF NumberOfBytesRead == 0 ; exit if the buffer is empty
invoke WriteConsole, hConsoleOutput, RcvBuffer,\ ; print out any characters recieved
NumberOfBytesRead, ADDR ConsoleWriteBytes, NULL
.ENDW
.ENDIF
.ENDW
invoke CloseHandle, hSerialPort ; close the serial port
invoke ExitProcess, NULL ; End the Program
END start
It fails to assemble due all the <BITRECORD> values below generate "error A2600: undefined symbol" messages:
mov SerialSettings.fOutxCtsFlow, FALSE ; No RTS
mov SerialSettings.fRtsControl, RTS_CONTROL_DISABLE ; No CTS
mov SerialSettings.fOutxDsrFlow, FALSE ; No DSR TX inhibiting
mov SerialSettings.fDsrSensitivity, FALSE ; No DSR RX inhibiting
mov SerialSettings.fDtrControl, DTR_CONTROL_ENABLE ; Enable DTR Signal
mov SerialSettings.fOutX, TRUE ; xOn/xOff enabled for TX
mov SerialSettings.fInX, FALSE ; Suspend Xon/Xoff for RCV
mov SerialSettings.fNull, TRUE ; Discard NULL bytes
mov SerialSettings.fAbortOnError, FALSE ; Do not Abort on Error
mov SerialSettings.fBinary, TRUE ; Binary Transfer
I checked windows.inc and I see they are listed as part of the DCB:
BITRECORD RECORD fBinary:1,fParity:1,fOutxCtsFlow:1,fOutxDsrFlow:1,fDtrControl:2,fDsrSensitivity:1,fTXContinueOnXoff:1,fOutX:1,fInX:1,fErrorChar:1,fNull:1,fRtsControl:2,fAbortOnError:1,fDummy2:17
DCB STRUCT
DCBlength DWORD ?
BaudRate DWORD ?
fbits BITRECORD <>
wReserved WORD ?
XonLim WORD ?
XoffLim WORD ?
ByteSize BYTE ?
Parity BYTE ?
StopBits BYTE ?
XonChar BYTE ?
XoffChar BYTE ?
ErrorChar BYTE ?
EofChar BYTE ?
EvtChar BYTE ?
wReserved1 WORD ?
DCB ENDS
Can someone tell me what I needs to be done to get past the errors?
Mike
You need to set the bits manually...
if 1
mov edx, 1*xxx+2*yyy+4*zzz+....
else
mov SerialSettings.fOutxCtsFlow, FALSE ; No RTS
mov SerialSettings.fRtsControl, RTS_CONTROL_DISABLE ; No CTS
mov SerialSettings.fOutxDsrFlow, FALSE ; No DSR TX inhibiting
mov SerialSettings.fDsrSensitivity, FALSE ; No DSR RX inhibiting
mov SerialSettings.fDtrControl, DTR_CONTROL_ENABLE ; Enable DTR Signal
mov SerialSettings.fOutX, TRUE ; xOn/xOff enabled for TX
mov SerialSettings.fInX, FALSE ; Suspend Xon/Xoff for RCV
mov SerialSettings.fNull, TRUE ; Discard NULL bytes
mov SerialSettings.fAbortOnError, FALSE ; Do not Abort on Error
mov SerialSettings.fBinary, TRUE ; Binary Transfer
mov SerialSettings.fParity, TRUE ; Parity Enabled
endif
There is also a SetField (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1205) macro in the MasmBasic package, but honestly, I've never used it.
See also
http://masm32.com/board/index.php?topic=6293.0
http://www.masmforum.com/board/index.php?topic=17452.0
http://www.masmforum.com/board/index.php?topic=13386.msg104286#msg104286
Thanks JJ, but something is still not right...
I read somewhere that the DCB and BITRECORD structure is being stored in reverse order in Windows.inc. Do you know if that is true?
When I run the program, it fails at SetComState if changes are made to the DCB settings - even if I only change the Baud Rate, Data Bits, Parity, and Stop bits to the suggested "19200,8,N,1" and all other parameters are left as is SetComState will fail.
If I don't change the serial settings read by GetComState and I bypass SetComState, then the WaitCommEvent function hangs, although I am sending data to the other end of the COM port the console only shows "Monitoring for Data". I even checked that data is received on the port using MS PortMon.
Here is the updated code:
Quote
.486
.model flat, stdcall
option casemap:none
include \masm32\include\masm32rt.inc
.data
szFrameError db "!" ; Display character for errors
displaystring1 db "Monitoring for Data:",0 ; Output display string
.data?
myDCB STRUCT
DCBlength DWORD ? ; sizeof(DCB)
BaudRate DWORD ? ; Baudrate at which running
fbits DWORD ?
XonLim WORD ? ; Transmit X-ON threshold
XoffLim WORD ? ; Transmit X-OFF threshold
ByteSize BYTE ? ; Number of bits/byte, 4-8
Parity BYTE ? ; 0-4=None,Odd,Even,Mark,Space
StopBits BYTE ? ; 0,1,2 = 1, 1.5, 2
XonChar BYTE ? ; Tx and Rx X-ON character
XoffChar BYTE ? ; Tx and Rx X-OFF character
ErrorChar BYTE ? ; Error replacement char
EofChar BYTE ? ; End of Input character
EvtChar BYTE ? ; Received Event character
wReserved1 WORD ? ; Fill for now.
myDCB ENDS
mBinary EQU 1
mParity EQU 2
mOutxCtsFlow EQU 4
mOutxDsrFlow EQU 8
mDtrControl EQU 16
mDsrSensitivity EQU 32
mTXContinueOnXoff EQU 64
mOutX EQU 128
mInX EQU 256
mErrorChar EQU 512
mNull EQU 1024
mRtsControl EQU 2048
mAbortOnError EQU 4096
hSerialPort DWORD ? ; handle for serial port
SerialSettings myDCB {?} ; settings for serial port
SerialTimeOuts COMMTIMEOUTS {?} ; timeout settings for serial port
NumberOfBytesRead DWORD ? ; rcv variable for bytes read from ReadFile
EvtMask DWORD ? ; rcv variable for comm event returned
SerialError DWORD ? ; holder for error occured
RcvBuffer DWORD ? ; variable for holding input to go to screen
hConsoleOutput DWORD ? ; Handle to the display console
ConsoleWriteBytes DWORD ? ; rcv variable for bytes written to console
.const
Comm1 db "COM1:", 0 ; Comm port constants
Comm2 db "COM2:", 0
Comm3 db "COM3:", 0
.code
start:
;-----------------------------
; Allocate a console for displaying output
;-----------------------------
invoke AllocConsole
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hConsoleOutput, eax
; do not process control codes, display thier hex equivalents
invoke SetConsoleMode, hConsoleOutput, ENABLE_WRAP_AT_EOL_OUTPUT
;-----------------------------
; Serial Port initialization
;-----------------------------
invoke CreateFile, ADDR Comm2, GENERIC_READ OR\ ; Open the Serial Port
GENERIC_WRITE,0, NULL, OPEN_EXISTING,0,NULL
cmp eax,INVALID_HANDLE_VALUE
jne ok0
print "Cant open COM port"
ok0:
mov hSerialPort, eax ; save the handle
mov SerialSettings.DCBlength, SIZEOF myDCB ; configure the Settings variable
invoke GetCommState, hSerialPort, ADDR SerialSettings ; fill it with the current settings
test eax,eax
jnz ok1
print "GetCommState failed"
jmp Exit
ok1:
mov SerialSettings.BaudRate, CBR_19200 ; Baud Rate
mov SerialSettings.ByteSize, 8 ; Data Bits: 8
mov SerialSettings.Parity, NOPARITY ; Parity: None
mov SerialSettings.StopBits, ONESTOPBIT ; Stop Bits: 1
;jmp setcomm
mov SerialSettings.fOutxCtsFlow, FALSE ; No RTS
mov SerialSettings.fRtsControl, RTS_CONTROL_DISABLE ; No CTS
mov SerialSettings.fOutxDsrFlow, FALSE ; No DSR TX inhibiting
mov SerialSettings.fDsrSensitivity, FALSE ; No DSR RX inhibiting
mov SerialSettings.fDtrControl, DTR_CONTROL_ENABLE ; Enable DTR Signal
mov SerialSettings.fOutX, TRUE ; xOn/xOff enabled for TX
mov SerialSettings.fInX, FALSE ; Suspend Xon/Xoff for RCV
mov SerialSettings.fNull, TRUE ; Discard NULL bytes
mov SerialSettings.fAbortOnError, FALSE ; Do not Abort on Error
mov SerialSettings.fBinary, TRUE ; Binary Transfer
mov SerialSettings.fParity, TRUE ; Parity Enabled
mov eax, (mDtrControl+mOutX+mNull+mBinary+fParity)
mov SerialSettings.fbits,eax
setcomm:
invoke SetCommState, hSerialPort, ADDR SerialSettings ; Apply the new settinsg
test eax,eax
jnz ok2
print "SetCommState failed"
jmp Exit
ok2:
; Set the Time-outs to occur immedietly with everything in the buffer
invoke GetCommTimeouts, hSerialPort, ADDR SerialTimeOuts
test eax,eax
jnz ok3
print "GetCommTimeouts failed"
jmp Exit
ok3:
mov SerialTimeOuts.ReadIntervalTimeout, MAXDWORD
mov SerialTimeOuts.ReadTotalTimeoutMultiplier, 0
mov SerialTimeOuts.ReadTotalTimeoutConstant, 0
mov SerialTimeOuts.WriteTotalTimeoutMultiplier, 0
mov SerialTimeOuts.WriteTotalTimeoutConstant, 0
invoke SetCommTimeouts, hSerialPort, ADDR SerialTimeOuts
test eax,eax
jnz ok4
print "SetCommTimeouts failed"
jmp Exit
ok4:
;Generate events for received bytes and errors
invoke SetCommMask, hSerialPort, (EV_RXCHAR OR EV_ERR)
;------------------------------------------------------
invoke WriteConsole, hConsoleOutput, ADDR displaystring1, \ ; display a prompt
SIZEOF displaystring1, ADDR NumberOfBytesRead, NULL
;-----------------------------
; Poll the serial port for RCV data
;-----------------------------
.WHILE TRUE ; Enter an endless loop
invoke WaitCommEvent, hSerialPort, ADDR EvtMask, NULL ; Hold up for either a character or an error
test eax,eax
jnz ok5
print "WaitCommEvent failed",13,10
jmp Exit
ok5:
;invoke WriteConsole, hConsoleOutput, ADDR displayx, \ ; display a prompt
; SIZEOF displayx, ADDR NumberOfBytesRead, NULL
.IF EvtMask == EV_ERR ; If an error came in...
invoke SetConsoleTextAttribute, hConsoleOutput,\ ; change to a red font
FOREGROUND_RED
invoke WriteConsole, hConsoleOutput, ADDR szFrameError,\ ; print an exclamation point
SIZEOF szFrameError, ADDR ConsoleWriteBytes, NULL
invoke SetConsoleTextAttribute, hConsoleOutput,\ ; change back to white font
FOREGROUND_BLUE OR FOREGROUND_GREEN OR FOREGROUND_RED
invoke ClearCommError, hSerialPort, ADDR SerialError, NULL; clear the error
.ENDIF
.IF EvtMask == EV_RXCHAR ; if a chracter was recieved...
.WHILE TRUE ; start a loop to empty out the serial port
invoke ReadFile, hSerialPort, RcvBuffer, SIZEOF\ ; Read in one DWORD from the serial port
RcvBuffer, ADDR NumberOfBytesRead, NULL
.BREAK .IF NumberOfBytesRead == 0 ; exit if the buffer is empty
invoke WriteConsole, hConsoleOutput, RcvBuffer,\ ; print out any characters recieved
NumberOfBytesRead, ADDR ConsoleWriteBytes, NULL
.ENDW
.ENDIF
.ENDW
Exit:
invoke CloseHandle, hSerialPort ; close the serial port
invoke ExitProcess, NULL ; End the Program
END start
Mike
Hi Mike,
We have discussed the DCB and BITRECORD structure in this thread: http://masm32.com/board/index.php?topic=6288.0
Thanks, Marinus - that thread is over three months old, I didn't remember ;-)
Final outcome was the _Record macro here: http://masm32.com/board/index.php?topic=6296.msg67393#msg67393
include \masm32\include\masm32rt.inc
include BitRecord.mac
.code
start:
print "00000000000000000010000000101101", 9, "expected", crlf
print bin$(_Record(TRUE,FALSE,TRUE,TRUE,DTR_CONTROL_HANDSHAKE:2,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,RTS_CONTROL_HANDSHAKE:2,FALSE,0)), crlf
inkey bin$(_RecordRev(0,FALSE,RTS_CONTROL_HANDSHAKE:2,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,DTR_CONTROL_HANDSHAKE:2,TRUE,TRUE,NULL,TRUE)), crlf
exit
end start
I disagree. The final correct result is to define the record properly, not like it is in windows.inc
The declaration of BITRECORD in Windows.inc is indeed wrong because follows the C/C++ convention, when in ASM the order is the inverse.
This is a sample with the modified BITRECORD :
.386
.model flat,stdcall
option casemap:none
;include \masm32\include\windows.inc
includelib \masm32\lib\msvcrt.lib
printf proto C :ptr, :vararg
BITRECORD RECORD fDummy2:17,fAbortOnError:1,fRtsControl:2, fNull:1,fErrorChar:1,fInX:1,fOutX:1, fTXContinueOnXoff:1,fDsrSensitivity:1,fDtrControl:2,fOutxDsrFlow:1,fOutxCtsFlow:1,fParity:1,fBinary:1
DCB STRUCT
DCBlength DWORD ?
BaudRate DWORD ?
fbits BITRECORD <>
wReserved WORD ?
XonLim WORD ?
XoffLim WORD ?
ByteSize BYTE ?
Parity BYTE ?
StopBits BYTE ?
XonChar BYTE ?
XoffChar BYTE ?
ErrorChar BYTE ?
EofChar BYTE ?
EvtChar BYTE ?
wReserved1 WORD ?
DCB ENDS
FieldSet MACRO SrcDotField, TheVal
LOCAL is, src, field
is INSTR <SrcDotField>, <.>
if is eq 0
.err <*** source.field required ***>
endif
src SUBSTR <SrcDotField>, 1, is-1
field SUBSTR <SrcDotField>, is+1
ifdifi <TheVal>, <eax>
mov eax, TheVal
endif
if field
shl eax, field
endif
and src, not mask field
add src, eax
ENDM
.data
fmt db "%c",0
.code
binPrint proc uses ebx esi value:dword
mov esi, value
mov ebx, 32
.while ebx
.if (esi & 80000000h)
INVOKE printf, offset fmt, "1"
.else
INVOKE printf, offset fmt, "0"
.endif
shl esi, 1
dec ebx
.endw
ret
binPrint endp
main proc
LOCAL bitrec : BITRECORD
mov bitrec, 0
FieldSet bitrec.fBinary, 1
FieldSet bitrec.fOutxCtsFlow, 0
FieldSet bitrec.fOutxDsrFlow, 0
FieldSet bitrec.fDtrControl, 1 ; DTR_CONTROL_ENABLE 0x01
FieldSet bitrec.fDsrSensitivity, 0
FieldSet bitrec.fOutX, 1
FieldSet bitrec.fInX, 0
FieldSet bitrec.fNull, 1
FieldSet bitrec.fRtsControl, 0 ; RTS_CONTROL_DISABLE 0x00
FieldSet bitrec.fAbortOnError, 0
mov eax, bitrec
INVOKE binPrint, eax
ret
main endp
end main
Thanks everyone for the replies. I agree with jimg that the windows.inc should be corrected. I just wonder if Hutch would agree.
Siekmanski: Thanks for the link to the other thread. I downloaded your RS232 code and it will be very useful.
JJ: Your Bitrecord macro was very helpful. The data is now in the correct order and SetCommState no longer generates an error.
Initially I was still unable to get redskull's "Simple Serial Port monitor" to show that any data was being received, but after looking the code over I noticed he left out the "ADDR" before the "RecvBuffer" a couple places, and once I added that it worked perfectly! Maybe he forgot to test it before posting, as the backwards bitrecord should also have prevented it from working unless an older version of MASM32 included the working windows.inc perhaps.
In case it helps anyone else, here is the working version of the Serial Port Monitor:
Quote
; Serial Port Monitor using WaitCommEvent. Original author: redskull
.486
.model flat, stdcall
option casemap:none
include \masm32\include\masm32rt.inc
include \masm32\BitRecord.mac
.data
szFrameError db "!" ; Display character for errors
displaystring1 db "Monitoring for Data:",0 ; Output display string
.data?
hSerialPort DWORD ? ; handle for serial port
SerialSettings DCB {?} ; settings for serial port
SerialTimeOuts COMMTIMEOUTS {?} ; timeout settings for serial port
NumberOfBytesRead DWORD ? ; rcv variable for bytes read from ReadFile
EvtMask DWORD ? ; rcv variable for comm event returned
SerialError DWORD ? ; holder for error occured
RcvBuffer DWORD ? ; variable for holding input to go to screen
hConsoleOutput DWORD ? ; Handle to the display console
ConsoleWriteBytes DWORD ? ; rcv variable for bytes written to console
.const
Comm1 db "COM1", 0 ; Comm port constants
Comm2 db "COM2", 0
Comm3 db "COM3", 0
Comm4 db "COM4", 0
.code
start:
;-----------------------------
; Allocate a console for displaying output
;-----------------------------
invoke AllocConsole
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hConsoleOutput, eax
; do not process control codes, display thier hex equivalents
invoke SetConsoleMode, hConsoleOutput, ENABLE_WRAP_AT_EOL_OUTPUT
;-----------------------------
; Serial Port initialization
;-----------------------------
invoke CreateFile, ADDR Comm4, GENERIC_READ OR\ ; Open the Serial Port
GENERIC_WRITE,0, NULL, OPEN_EXISTING,0,NULL
cmp eax,INVALID_HANDLE_VALUE
jne ok0
print "Cant open COM port"
jmp Exit
ok0:
mov hSerialPort, eax ; save the handle
mov SerialSettings.DCBlength, SIZEOF DCB ; configure the Settings variable
invoke GetCommState, hSerialPort, ADDR SerialSettings ; fill it with the current settings
test eax,eax
jnz ok1
print "GetCommState failed"
jmp Exit
ok1:
mov SerialSettings.BaudRate, CBR_19200 ; Baud Rate
mov SerialSettings.ByteSize, 8 ; Data Bits: 8
mov SerialSettings.Parity, NOPARITY ; Parity: None
mov SerialSettings.StopBits, ONESTOPBIT ; Stop Bits: 1
;mov SerialSettings.fRtsControl, RTS_CONTROL_DISABLE ; No CTS
;mov SerialSettings.fOutxDsrFlow, FALSE ; No DSR TX inhibiting
;mov SerialSettings.fDsrSensitivity, FALSE ; No DSR RX inhibiting
;mov SerialSettings.fDtrControl, DTR_CONTROL_ENABLE ; Enable DTR Signal
;mov SerialSettings.fOutX, TRUE ; xOn/xOff enabled for TX
;mov SerialSettings.fInX, FALSE ; Suspend Xon/Xoff for RCV
;mov SerialSettings.fNull, TRUE ; Discard NULL bytes
;mov SerialSettings.fAbortOnError, FALSE ; Do not Abort on Error
;mov SerialSettings.fBinary, TRUE ; Binary Transfer
;mov SerialSettings.fParity, TRUE ; Parity Enabled
mov eax,(_Record(NULL,FALSE,RTS_CONTROL_DISABLE:2,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,DTR_CONTROL_DISABLE:2,FALSE,FALSE,FALSE,TRUE))
mov SerialSettings.fbits,eax
;print bin$(eax), 32
; fBinary: 1; /* Binary Mode (skip EOF check) */
; fParity: 1; /* Enable parity checking */
; fOutxCtsFlow:1; /* CTS handshaking on output */
; fOutxDsrFlow:1; /* DSR handshaking on output */
; fDtrControl:2; /* DTR Flow control */
; fDsrSensitivity:1; /* DSR Sensitivity */
; fTXContinueOnXoff:1; /* Continue TX when Xoff sent */
; fOutX: 1; /* Enable output X-ON/X-OFF */
; fInX: 1; /* Enable input X-ON/X-OFF */
; fErrorChar: 1; /* Enable Err Replacement */
; fNull: 1; /* Enable Null stripping */
; fRtsControl:2; /* Rts Flow control */
; fAbortOnError:1; /* Abort reads and writes on Error */
; NULL
setcomm:
invoke SetCommState, hSerialPort, ADDR SerialSettings ; Apply the new settinsg
test eax,eax
jnz ok2
print "SetCommState failed"
jmp Exit
ok2:
; Set the Time-outs to occur immedietly with everything in the buffer
invoke GetCommTimeouts, hSerialPort, ADDR SerialTimeOuts
test eax,eax
jnz ok3
print "GetCommTimeouts failed"
jmp Exit
ok3:
mov SerialTimeOuts.ReadIntervalTimeout, MAXDWORD
mov SerialTimeOuts.ReadTotalTimeoutMultiplier, 1
mov SerialTimeOuts.ReadTotalTimeoutConstant, 1
mov SerialTimeOuts.WriteTotalTimeoutMultiplier, 1
mov SerialTimeOuts.WriteTotalTimeoutConstant, 1
invoke SetCommTimeouts, hSerialPort, ADDR SerialTimeOuts
test eax,eax
jnz ok4
print "SetCommTimeouts failed"
jmp Exit
ok4:
;Generate events for received bytes and errors
invoke SetCommMask, hSerialPort, (EV_RXCHAR OR EV_ERR)
;------------------------------------------------------
invoke WriteConsole, hConsoleOutput, ADDR displaystring1, \ ; display a prompt
SIZEOF displaystring1, ADDR NumberOfBytesRead, NULL
;-----------------------------
; Poll the serial port for RCV data
;-----------------------------
.WHILE TRUE ; Enter an endless loop
invoke WaitCommEvent, hSerialPort, ADDR EvtMask, NULL ; Hold up for either a character or an error
test eax,eax
jnz ok5
print "WaitCommEvent failed",13,10
jmp Exit
ok5:
.IF EvtMask == EV_ERR ; If an error came in...
invoke SetConsoleTextAttribute, hConsoleOutput,\ ; change to a red font
FOREGROUND_RED
invoke WriteConsole, hConsoleOutput, ADDR szFrameError,\ ; print an exclamation point
SIZEOF szFrameError, ADDR ConsoleWriteBytes, NULL
invoke SetConsoleTextAttribute, hConsoleOutput,\ ; change back to white font
FOREGROUND_BLUE OR FOREGROUND_GREEN OR FOREGROUND_RED
invoke ClearCommError, hSerialPort, ADDR SerialError, NULL; clear the error
.ENDIF
.IF EvtMask == EV_RXCHAR ; if a chracter was recieved...
.WHILE TRUE ; start a loop to empty out the serial port
invoke ReadFile, hSerialPort, ADDR RcvBuffer, SIZEOF\ ; Read in one DWORD from the serial port
RcvBuffer, ADDR NumberOfBytesRead, NULL
mov eax,NumberOfBytesRead
.BREAK .IF NumberOfBytesRead == 0 ; exit if the buffer is empty
invoke WriteConsole, hConsoleOutput, ADDR RcvBuffer,\ ; print out any characters recieved
NumberOfBytesRead, ADDR ConsoleWriteBytes, NULL
.ENDW
.ENDIF
.ENDW
Exit:
invoke CloseHandle, hSerialPort ; close the serial port
invoke ExitProcess, NULL ; End the Program
END start
Mike
[Edit: typo]
Thanks for posting the code, Mike. It builds fine but doesn't work on my machine, probably no active port ("can't find the specified file") ::)
JJ: If your COM port is a higher number then COM4, then it needs to be defined like this:
Comm5 db "\\.\COM5", 0
Mike
It seems this notebook really has NO COM port :(
Quote from: jj2007 on September 22, 2017, 08:33:47 AM
It seems this notebook really has NO COM port :(
I have not seen a computer with a serial adapter since last century.
But there are still a couple of uses for virtual serial ports.
Mike,
> I just wonder if Hutch would agree.
In a Windows world where 32 bit is in its twilight, 64 bit is on the rise, I simply don't care about ancient compatibility. There has always been a solution to the problem you are facing, write your own and you will get exactly what you want. I have 64 bit MASM code to write.
Quote from: hutch-- on September 22, 2017, 04:07:17 PM
I have 64 bit MASM code to write.
:biggrin: That's the attitude! :icon14: