Introduction
Welcome to CSerialPort
, a freeware MFC class to wrap access to the Win32 APIs dealing with serial ports.
Features
- Simple and clean C++ interface.
- Uses C++ exceptions in preference to the normal Win32 return value mechanism. This ensures that code which uses
CSerialPort
is more robust.
- Unicode enabled, supports linking to MFC statically and all code compiles cleanly at warning level 4.
- Supports overlapped, blocking and callback usage models of the serial port. (Callback is only supported on NT).
Usage
- To use the class in your code, simply include serialport.cpp in your project and
#include serialport.h
in which ever of your modules needs to make calls to the class.
- To see the code in action, have a look at the module app.cpp in the sample app.
A brief example is as follows:
try {
CSerialPort port;
port.Open(1, 1200, CSerialPort::NoParity, 8,
CSerialPort::OneStopBit,
CSerialPort::XonXoffFlowControl);
char sBuf[] = "This should appear on the serial port";
port.Write(sBuf, strlen(sBuf));
port.Flush();
port.Close();
}
catch (CSerialException* pEx)
{
TRACE(_T("Handle Exception, Message:%s\n"),
pEx->GetErrorMessage());
pEx->Delete();
}
History
- V1.0 (31st May 1999)
- V1.01 (3rd June 1999)
- Fixed problem with code using
CancelIo
function which does not exist on 95.
- Fixed leaks which can occur in sample app when an exception is thrown.
- V1.02 (16th June 1999)
- Fixed a bug whereby
CString::ReleaseBuffer
was not being called in CSerialException::GetErrorMessage
.
- V1.03 (29th September 1999)
- Fixed a simple copy and paste bug in
CSerialPort::SetDTR
.
APIReference
The API consists of the classes: CSerialException
and CSerialPort
. They have the following member functions and variables:
CSerialException::CSerialException
CSerialException( DWORD dwError = 0);
Parameters
dwError
- The error that caused the exception.
Remarks
This member function is called when a CSerialException
object is created. To throw a CSerialException
, call the global function AfxThrowSerialException
. If you call it using the default value for dwError
, then internally it will call GetLastError
for you.
CSerialException::GetErrorMessage
virtual BOOL GetErrorMessage( LPTSTR lpszError,
UINT nMaxError, PUINT pnHelpContext = NULL );
CString GetErrorMessage();
Return Value
- Nonzero if the function is successful; otherwise 0 if no error message text is available.
- A
CString
representation of the error.
Parameters
lpszError
- A pointer to a buffer that will receive an error message.
nMaxError
- The maximum number of characters the buffer can hold, including the NULL
terminator.
pnHelpContext
- The address of a UINT
that will receive the help context ID. If NULL
, no ID will be returned.
Remarks
Call this member function to provide text about an error that has occurred.
CSerialException::m_dwError
Remarks
The error that caused the exception. This error value is a system error code as found in WINERROR.H.
For a list of Win32 error codes, see Error Codes in the Win32 SDK.
CSerialPort::CSerialPort
CSerialPort();
Remarks
Standard C++ constructor for the class. Internally it just sets up the member variables to default values.
CSerialPort::~CSerialPort
~CSerialPort();
Remarks
Standard C++ destructor for the class. It will ensure that the comms port is closed if it is open.
CSerialException::Open
void Open( int nPort, DWORD dwBaud = 9600,
Parity parity = NoParity, BYTE DataBits = 8,
StopBits stopbits = OneStopBit,
FlowControl fc = NoFlowControl, BOOL bOverlapped = FALSE);
throw( CSerialException );
Parameters
nPort
- The communications port to open.
dwBaud
- The baud rate to use
parity
- The parity to use. parity
is an enum
with the following values: enum Parity
{
EvenParity,
MarkParity,
NoParity,
OddParity,
SpaceParity
};
Databits
- The number of data bits to use.
stopbits
- The number of stop bits to use. stopbits
is an enum
with the following values: enum StopBits
{
OneStopBit,
OnePointFiveStopBits,
TwoStopBits
};
fc
- The flow control method to use. fc
is an enum
with the following values: enum FlowControl
{
NoFlowControl,
CtsRtsFlowControl,
CtsDtrFlowControl,
DsrRtsFlowControl,
DsrDtrFlowControl,
XonXoffFlowControl
};
bOverlapped
- TRUE
if you want to open in overlapped mode, otherwise FALSE
to use blocking calls.
Remarks
Call this member function to open a communications port. Internally the class will use CreateFile
to open the comms port (handling the case where the port number if greater than 9) and then uses SetState
to set the various RS-232 settings as specified via the function parameters. If an error occurs, a CSerialException
will be thrown.
CSerialPort::Close
Close();
Remarks
The corollary function to Open
. Just closes the comms port if already open.
CSerialPort::Attach
void Attach(HANDLE hComm);
Parameters
hComm
- The SDK handle of the open comms port.
Remarks
Allows you to attach a CSerialPort
instance to an existing SDK comms port handle. This function is similar in behavior to the CWnd::Attach
function provided in MFC.
CSerialPort::Detach
HANDLE Detach();
Return Value
The SDK comms port HANDLE.
Remarks
Corollary function to Attach
. This function is similar in behavior to the CWnd::Detach
function provided in MFC.
CSerialPort::operator HANDLE
operator HANDLE();
Return Value
The SDK comms port HANDLE.
Remarks
Use this operator to get the handle of the underlying comms port. You can use this handle to call the Windows APIs directly.
CSerialPort::IsOpen
BOOL IsOpen() const
Return Value
TRUE
if the comms port is open, otherwise FALSE
.
CSerialPort::Dump
void Dump(CDumpContext& dc) const
Remarks
Standard MFC diagnostic support function.
CSerialPort::Read\ReadEx
DWORD Read(void* lpBuf, DWORD dwCount);
BOOL Read(void* lpBuf, DWORD dwCount, OVERLAPPED& overlapped);
void ReadEx(void* lpBuf, DWORD dwCount);
throw( CSerialException );
Return Value
- The number of bytes read.
TRUE
if the overlapped read completed synchronously, FALSE
if the operation is to be completed asynchronously.
Parameters
lpBuf
- Points to the buffer to read the data into from the serial port.
dwCount
- Specifies the number of bytes to read from the serial port.
overlapped
- reference to an OVERLAPPED
structure. This is required if the port was opened in overlapped mode.
Remarks
These 3 functions are wrappers for the SDK calls ReadFile
and ReadFileEx
. The 2nd version of Read
is the overlapped version.
CSerialPort::Write\WriteEx
DWORD Write(const void* lpBuf, DWORD dwCount);
BOOL Write(const void* lpBuf, DWORD dwCount, OVERLAPPED& overlapped);
void WriteEx(const void* lpBuf, DWORD dwCount);
throw( CSerialException );
Return Value
- The number of bytes written.
TRUE
if the overlapped write completed synchronously, FALSE
if the operation is to be completed asynchronously.
Parameters
lpBuf
- Points to the buffer containing the data to be written to the serial port.
dwCount
- Specifies the number of bytes to write to the serial port.
overlapped
- reference to an OVERLAPPED
structure. This is required if the port was opened in overlapped mode.
Remarks
These 3 functions are wrappers for the SDK calls WriteFile
and WriteFileEx
. The 2nd version of Write
is the overlapped version.
CSerialPort::TransmitChar
void TransmitChar(char cChar) const
throw( CSerialException );
Remarks
Simple wrapper for the TransmitCommChar
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::GetOverlappedResult
void GetOverlappedResult(OVERLAPPED& overlapped,
DWORD& dwBytesTransferred, BOOL bWait)
throw( CSerialException );
Remarks
Simple wrapper for the GetOverlappedResult
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::CancelIo
void CancelIo()
throw( CSerialException );
Remarks
Simple wrapper for the CancelIo
SDK function call. See the Win32 SDK documentation for further details. Please note that this function is only available on NT 4, or Windows 98 or later. In version 1.0 of CSerialPort
, this would cause code developed with it to fail to load on Windows 95 with an error about a missing export. This problem has been rectified in v1.01 of CSerialPort
.
CSerialPort::GetConfig
void GetConfig(COMMCONFIG& config)
throw( CSerialException );
Remarks
Simple wrapper for the GetCommConfig
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::GetDefaultConfig
static void GetDefaultConfig(int nPort, COMMCONFIG& config)
throw( CSerialException );
Remarks
Simple wrapper for the GetDefaultCommConfig
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::SetConfig
void SetConfig(COMMCONFIG& config)
throw( CSerialException );
Remarks
Simple wrapper for the SetCommConfig
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::SetDefaultConfig
static void SetDefaultConfig(int nPort, COMMCONFIG& config)
throw( CSerialException );
Remarks
Simple wrapper for the SetDefaultCommConfig
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::ClearBreak
void ClearBreak()
throw( CSerialException );
Remarks
Simple wrapper for the ClearCommBreak
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::SetBreak
void SetBreak()
throw( CSerialException );
Remarks
Simple wrapper for the SetCommBreak
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::ClearError
void ClearError(DWORD& dwErrors)
throw( CSerialException );
Remarks
Simple wrapper for the ClearCommError
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::GetStatus
void GetStatus(COMMSTAT& stat)
throw( CSerialException );
Remarks
Simple wrapper for the GetCommStatus
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::GetState
void GetState(DCB& dcb)
throw( CSerialException );
Remarks
Simple wrapper for the GetCommState
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::SetState
void SetState(DCB& dcb)
throw( CSerialException );
Remarks
Simple wrapper for the SetCommState
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::Escape
void Escape(DWORD dwFunc)
throw( CSerialException );
Remarks
Simple wrapper for the EscapeCommFunction
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::ClearDTR
void ClearDTR()
throw( CSerialException );
Remarks
Calls the Escape
function using the constant CLRDTR
which lowers the DTR line.
CSerialPort::ClearRTS
void ClearRTS()
throw( CSerialException );
Remarks
Calls the Escape
function using the constant CLRRTS
which lowers the RTS line.
CSerialPort::SetDTR
void SetDTR()
throw( CSerialException );
Remarks
Calls the Escape
function using the constant SETDTR
which raises the DTR line.
CSerialPort::SetRTS
void SetRTS()
throw( CSerialException );
Remarks
Calls the Escape
function using the constant SETRTS
which raises the RTS line.
CSerialPort::SetXOFF
void SetXOFF()
throw( CSerialException );
Remarks
Calls the Escape
function using the constant SETXOFF
which causes transmission to act as if an XOFF character has been received..
CSerialPort::SetXON
void SetXON()
throw( CSerialException );
Remarks
Calls the Escape
function using the constant SETXON
which causes transmission to act as if an XON character has been received..
CSerialPort::GetProperties
void GetProperties(COMMPROP& properties)
throw( CSerialException );
Remarks
Simple wrapper for the GetCommProperties
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::GetModemStatus
void GetModemStatus(DWORD& dwModemStatus)
throw( CSerialException );
Remarks
Simple wrapper for the GetCommModemStatus
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::SetTimeouts
void SetTimeouts(COMMTIMEOUTS& timeouts)
throw( CSerialException );
Remarks
Simple wrapper for the SetCommTimeouts
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::GetTimeouts
void GetTimeouts(COMMTIMEOUTS& timeouts)
throw( CSerialException );
Remarks
Simple wrapper for the GetCommTimeouts
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::Set0Timeout
void Set0Timeout()
throw( CSerialException );
Remarks
Configures both send and receive timeouts to be 0. This causes writes to return immediately, and for reads to return with whatever data is waiting in the receive buffer, rather than wait for the specified amount of bytes to arrive.
CSerialPort::Set0WriteTimeout
void Set0WriteTimeout()
throw( CSerialException );
Remarks
Configures the send timeouts to be 0. This cause writes to return immediately.
CSerialPort::Set0ReadTimeout
void Set0ReadTimeout()
throw( CSerialException );
Remarks
Configure the receive timeout to be 0. This causes reads to return with whatever data is waiting in the receive buffer rather than wait for the specified amount of bytes to arrive.
CSerialPort::SetMask
void SetMask(DWORD dwMask)
throw( CSerialException );
Remarks
Simple wrapper for the SetCommMask
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::GetMask
void GetMask(DWORD& dwMask)
throw( CSerialException );
Remarks
Simple wrapper for the GetCommMask
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::WaitEvent
void WaitEvent(DWORD& dwMask)
void WaitEvent(DWORD& dwMask, OVERLAPPED& overlapped)
throw( CSerialException );
Remarks
Simple wrapper for the WaitCommEvent
SDK function call. The second version of WaitEvent
is the overlapped version which will return immediately and you can wait for the manual reset event member of the OVERLAPPED
structure to become signaled in your code. See the Win32 SDK documentation for further details.
CSerialPort::Flush
void Flush()
throw( CSerialException );
Remarks
Simple wrapper for the FlushFileBuffers
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::Purge
void Purge(DWORD dwFlags)
throw( CSerialException );
Remarks
Simple wrapper for the PurgeComm
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::TerminateOutstandingWrites
void TerminateOutstandingWrites()
throw( CSerialException );
Remarks
Calls the Purge
function using the constant PURGE_TXABORT
which terminates all outstanding write operations and returns immediately, even if the write operations have not been completed.
CSerialPort::TerminateOutstandingReads
void TerminateOutstandingReads()
throw( CSerialException );
Remarks
Calls the Purge
function using the constant PURGE_RXABORT
which terminates all outstanding read operations and returns immediately, even if the read operations have not been completed.
CSerialPort::ClearWriteBuffer
void ClearWriteBuffer()
throw( CSerialException );
Remarks
Calls the Purge
function using the constant PURGE_TXCLEAR
which clears the output buffer (if the device driver has one)..
CSerialPort::ClearReadBuffer
void ClearReadBuffer()
throw( CSerialException );
Remarks
Calls the Purge
function using the constant PURGE_RXCLEAR
which clears the input buffer (if the device driver has one)..
CSerialPort::Setup
void Setup(DWORD dwInQueue, DWORD dwOutQueue)
throw( CSerialException );
Remarks
Simple wrapper for the SetupComm
SDK function call. See the Win32 SDK documentation for further details.
CSerialPort::OnCompletion
virtual void OnCompletion(DWORD dwErrorCode,
DWORD dwCount, LPOVERLAPPED lpOverlapped);
throw( CSerialException );
Parameters
dwErrorCode
- Specifies the I/O completion status. This parameter may be one of the following values:
Value |
Meaning |
0 |
The I/O was successful. |
ERROR_HANDLE_EOF |
The ReadFileEx function tried to read past the end of the file. |
dwCount
- Specifies the number of bytes transferred. If an error occurs, this parameter is zero.
lpOverlapped
- Points to the OVERLAPPED
structure specified by the asynchronous I/O function.
Remarks
This function is called as the completion routine for any asynchronous calls to WriteEx
or ReadEx
. In your derived class from CSerialPort
, you can override this function to perform your own specific code in reaction to an asynchronous call completion. Don't forget to call the parent version, namely this function CSerialPort::OnCompletion
as it handles the cleanup of the memory allocated for the lpOverlapped
parameter.
Planned Enhancements
- Provide a better sample app. At the moment, it's very much a test program which tests all of the functions.
- If you have any other suggested improvements, please let me know so that I can incorporate them into the next release.
Contacting the Author
Please send any comments or bug reports to me via email. For any updates to this article, check my site here.