I've been fooling around with serial ports for the last week or so, and i thought I would share what I came up with. This program just monitors a serial port for any incoming data, and displays it in a console window. All the settings are hard coded, so it has to get reassembled for your particular purpose. It *seems* to work, but i have limited ability to fully test it. As always, suggestions, comments, bug reports, flames, and caustic insults are highly encouraged. Thanks again to everyone for helping to edu-ma-cate me.
alan
.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
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