Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Serial Port Programming in Win32

190 views
Skip to first unread message

Terence Wilson

unread,
Oct 31, 1996, 3:00:00 AM10/31/96
to

I'm involved in a project which will be using the serial
port to control a scientific instrument. Does anyone have
a good reference on serial port programming with MFC / Win32?

Also, are there any class libraries that encapsulate serial
port programming?

Thanks,

Terence Wilson.

Matt Raffel

unread,
Oct 31, 1996, 3:00:00 AM10/31/96
to

t...@latte.com (Terence Wilson) wrote:

Greenleaf is about the best of the libraries I have used.
The current version of Greenleaf includes a C++ class
wrapper for their library.


=====================================================
The man who doesn't read good books has no advantage over
the man who can't read them. [Mark Twain]
--
For my public PGP key, see my web page at
http://www.mindspring.com/~isoftdev/homeofmatt.html


James Cosand

unread,
Nov 3, 1996, 3:00:00 AM11/3/96
to

----------
> From: Terence Wilson <t...@latte.com>
> Newsgroups: comp.os.ms-windows.programmer.misc;
comp.os.ms-windows.programmer.tools.mfc; comp.os.ms-windows.programmer.mfc;
microsoft.public.vc.mfc; microsoft.public.vc.mfc.docview;
microsoft.public.win32.programmer.tools
> Subject: Serial Port Programming in Win32
> Date: Thursday, October 31, 1996 2:33 AM


>
> I'm involved in a project which will be using the serial
> port to control a scientific instrument. Does anyone have
> a good reference on serial port programming with MFC / Win32?
>
> Also, are there any class libraries that encapsulate serial
> port programming?
>

> Thanks,
>
> Terence Wilson.
>

I have been working on a similar project for some time.

I have a project at work (Delco Electronics) where I have a custom board
which uses an embedded microcontroller to communicate over a J1850 serial
communications bus, a second propriety serial bus, and also supports other
busses by plugin "mez" boards. This board communicates with a host
computer via RS232.

My app has to be event driven, and because of very limited buffering on
the embedded controller, my app must be able to receive, decode, build, and
send an appropriate reply within 20 milliseconds on a continuos basis or
the onboard buffers will overflow.

I did not want to use an OLE control. I felt the added overhead involved
with an OLE control would add to the processing time in my application, and
due to the buffer concerns I wanted my code to run as efficiently as
possible. My solution was to implement my code using the win32 API.

The application I have is an MFC Dialog based app. I have removed the
'#define VCEXTRALEAN' (I may have mispelled this) in STDAFX.H. (If you do
not comment this out, some of the comm port functions will not compile)

My SetupCommPort() function looks like this: (I have deleted a lot of
things that are not importent to this discussion)

****************************************************************************

*********

void CMemoryEditorDlg::CSetupCommPort(UINT Port, UINT Baud)
{
// gain ownership of the comm section
EnterCriticalSection(&CommSync);

// prepare port strings
sprintf(port, "COM%d", Port);
sprintf(baud, "baud=%d parity=N data=8 stop=1", Baud);


hCom1 = CreateFile(port, // Communications Port string variable
GENERIC_READ | GENERIC_WRITE, // Read/Write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // hTemplate must be NULL for comm devices

if (hCom1 == INVALID_HANDLE_VALUE)
{
CProcessErrorMessage("CreateFile()");
}

// set commtimeout parameters
commtimeouts.ReadIntervalTimeout = 1000;
commtimeouts.ReadTotalTimeoutMultiplier = 1000;
commtimeouts.ReadTotalTimeoutConstant = 1000;
commtimeouts.WriteTotalTimeoutMultiplier = 1000;
commtimeouts.WriteTotalTimeoutConstant = 1000;

if (SetCommTimeouts(hCom1, &commtimeouts))
{
if (SetCommMask(hCom1, EV_RXCHAR))
{
if (GetCommState(hCom1, &dcb))
{
if (BuildCommDCB(baud, &dcb))
{
if (SetCommState(hCom1, &dcb))
{
// normal opperation.. continue
}
else
{
CProcessErrorMessage("SetCommState()");
}
}
else
{
CProcessErrorMessage("BuildCommDCB()");
}
}
else
{
CProcessErrorMessage("GetCommState()");
}
}
else
{
CProcessErrorMessage("SetCommMask()");
}
}
else
{
CProcessErrorMessage("SetCommTimeouts()");
}

PurgeComm(hCom1, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT |
PURGE_TXABORT);

// release critical section
LeaveCriticalSection(&CommSync);

// startup comm port thread
AfxBeginThread(CommThreadProcess, this);
}

****************************************************************************

**********
I use a thread process to handle communications on the port. The
important parts of this function are:

****************************************************************************

***********

UINT CMemoryEditorDlg::CommThreadProcess(LPVOID pParam)
{
CMemoryEditorDlg *dlg = (CMemoryEditorDlg*)pParam;
ASSERT_KINDOF(CMemoryEditorDlg, dlg);

dlg->m_bCommThreadAlive = TRUE;

COMSTAT comstat;
unsigned char *RXBuff = new unsigned char[2];
char *RXString = new char[100];
DWORD dwError = 0, BytesTransfered = 0, Event = 0;
DWORD BytesRead = 0;
BOOL bRead = TRUE, bResult = TRUE, LastByteFF = FALSE;
UINT RXStringPosition = 0;

PurgeComm(dlg->hCom1, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT |
PURGE_TXABORT);

for (;;) { // begin forever loop

bResult = WaitCommEvent(dlg->hCom1, &Event, &dlg->ov);

if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// Do nothing and continue
break;
}
default:
{
dlg->CProcessErrorMessage("WaitCommEvent()");
break;
}
}
}
else
{
// Check Comm Errors.. If zero bytes left in buffer, loop back through
// WaitCommEvent(). If bytes are left, proceed through to read.
bResult = ClearCommError(dlg->hCom1, &dwError, &comstat);

if (comstat.cbInQue == 0)
{
continue;
}
}

Event = WaitForMultipleObjects(2, dlg->m_hEventArray, FALSE, INFINITE);

switch (Event)
{
case 0:
{
// Shutdown thread
dlg->m_bCommThreadAlive = FALSE;
delete[] RXString;
delete[] RXBuff;

AfxEndThread(100);
break;
}
case 1:
{
// RX Char event
LastByteFF = FALSE;
EnterCriticalSection(&dlg->CommSync);

bResult = ClearCommError(dlg->hCom1, &dwError, &comstat);

LeaveCriticalSection(&dlg->CommSync);

for (;;) { // start forever loop

if (comstat.cbInQue == 0)
{
break;
}

EnterCriticalSection(&dlg->CommSync);

if (bRead)
{
bResult = ReadFile(dlg->hCom1, // Handle to COMM port
RXBuff, // RX Buffer Pointer
1, // Read one byte
&BytesRead, // Stores number of bytes read
&dlg->ov); // pointer to the overlapped structure

// deal with the error code
if (!bResult)
{
switch (dwError = GetLastError())
{
// asynchronous i/o is still in progress
case ERROR_IO_PENDING:
{
bRead = FALSE;
break;
}
default:
{
dlg->CProcessErrorMessage("ReadFile()");
break;
}
}
}
else
{
bRead = TRUE;
}
} // cl0se if (bRead)

if (!bRead)
{
bRead = TRUE;

bResult = GetOverlappedResult(dlg->hCom1, // Handle to COMM port
&dlg->ov, // Overlapped structure
&BytesRead, // Stores number of bytes read
TRUE); // Wait flag

// deal with the error code
if (!bResult)
{
dlg->CProcessErrorMessage("GetOverlappedResults() in ReadFile()");
}
} // close if (!bRead)

LeaveCriticalSection(&dlg->CommSync);

// Code to process received message deleted here

} // end forever loop

break;

} // end case 1

} // end switch

} // close forever loop

return 0;

}

****************************************************************************

********************

As you can see, I use critical section objects to keep the comm port
process in sync. I do the send function from the main app thread, but only
after the send (writefile()) function gets ownership of the critical
section object, as follows:

****************************************************************************

*********************

void CMemoryEditorDlg::CSendMessage(char *TXString)
{
EnterCriticalSection(&CommSync);

if (bWrite)
{
BytesSent = 0;
ov.Offset = 0;
ov.OffsetHigh = 0;
PurgeComm(hCom1, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT |
PURGE_TXABORT);

bResult = WriteFile(hCom1, // Handle to COMM Port
TXByteArray, // Pointer to message buffer in calling finction
TXByteArrayLength, // Length of message to send
&BytesSent, // Where to store the number of bytes sent
&ov); // Overlapped structure

// deal with any error codes
if (!bResult)
{
DWORD dwError = GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:
{
// continue to GetOverlappedResults()
BytesSent = 0;
bWrite = FALSE;
break;
}
default:
{
// all other error codes
CProcessErrorMessage("WriteFile()");
}
}
}
else
{
LeaveCriticalSection(&CommSync);
}
} // end if(bWrite)

if (!bWrite)
{
bWrite = TRUE;

bResult = GetOverlappedResult(hCom1, // Handle to COMM port
&ov, // Overlapped structure
&BytesSent, // Stores number of bytes sent
TRUE); // Wait flag

LeaveCriticalSection(&CommSync);

// deal with the error code
if (!bResult)
{
CProcessErrorMessage("GetOverlappedResults() in WriteFile()");
}
} // end if (!bWrite)

// Verify that the data size send equals what we tried to send
if (BytesSent != TXByteArrayLength)
{
TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length:
%d\n", BytesSent, TXByteArrayLength);
}

}

***********************************************************

This code represents the final results of about 6 months of frustration,
trial and error, plus a lot of research. It works very well, and meets all
of my design requirements.

As long as this reply is, I have omitted a lot of information. If you
have any questions, please post it here and reply via EMAIL to
JHCO...@IN.NET.

regards,


James Cosand
Software Engineer
Delco Electronics Audio Systems
Kokomo, Indiana


Michael J. Lambert

unread,
Nov 4, 1996, 3:00:00 AM11/4/96
to

Hey James,

You might check out Samuel Blackburn's WFC code samples (can't remember
the web sight right now -- yahoo it). They incorporate serial
communication stuff in an MFC style. Really has a great deal of
information.
The MTTTY sample (serial communication with WIN32 @
http://207.68.137.9/win32dev/ ) is also worth looking at in detail for
adding multithreading to your serial communication. The latest MSJ had a
short article multithreaded MFC if your interested.

James Cosand <jhco...@in.net> wrote in article
<01bbc9ae$c96dcf50$74caa0cd@JHCOSAND>...


> > I'm involved in a project which will be using the serial
> > port to control a scientific instrument. Does anyone have
> > a good reference on serial port programming with MFC / Win32?
> >

end


Microsoft Win32 Developers.url

pat...@suba.com

unread,
Nov 5, 1996, 3:00:00 AM11/5/96
to isof...@atl.mindspring.com

Matt Raffel wrote:

>
> t...@latte.com (Terence Wilson) wrote:
>
> >I'm involved in a project which will be using the serial
> >port to control a scientific instrument. Does anyone have
> >a good reference on serial port programming with MFC / Win32?
>
> >Also, are there any class libraries that encapsulate serial
> >port programming?
>
> Greenleaf is about the best of the libraries I have used.
> The current version of Greenleaf includes a C++ class
> wrapper for their library.
>
> =====================================================
> The man who doesn't read good books has no advantage over
> the man who can't read them. [Mark Twain]
> --
> For my public PGP key, see my web page at
> http://www.mindspring.com/~isoftdev/homeofmatt.html

There's also a book available called Visual C++ Power Tools by Richard
Leinecker and Jamie Nye that includes a chapter on serial and socket
communications with source code and libraries for two classes
encapsulating everything you need in building up and tearing down a
serial communications session.

pat...@suba.com

John Lee

unread,
Nov 6, 1996, 3:00:00 AM11/6/96
to

On Thu, 31 Oct 1996 07:33:41 GMT, t...@latte.com (Terence Wilson)
wrote:

>I'm involved in a project which will be using the serial
>port to control a scientific instrument. Does anyone have
>a good reference on serial port programming with MFC / Win32?
>
>Also, are there any class libraries that encapsulate serial
>port programming?
>

>Thanks,
>
>Terence Wilson.
Are there source codes for VB???


David A. Fuess

unread,
Nov 6, 1996, 3:00:00 AM11/6/96
to

pat...@suba.com wrote:

>Matt Raffel wrote:
>There's also a book available called Visual C++ Power Tools by Richard
>Leinecker and Jamie Nye that includes a chapter on serial and socket
>communications with source code and libraries for two classes
>encapsulating everything you need in building up and tearing down a
>serial communications session.

I bought that book. While some of the stuff is pretty good, the
communications are pre-VC++ 4.0 hence do not work under the new
releases of VC++. Perhaps the author will update the code someday and
publish a second edition.

Dave

---------- Signature follows ----------
fu...@netcom.com (David A. Fuess)

David A. Fuess

unread,
Nov 6, 1996, 3:00:00 AM11/6/96
to

ta...@monmouth.com (John Lee) wrote:

>Are there source codes for VB???

You don't really need codes for VB. It was the origin of the OCX which
is delivered with VC++ 4.2! VB has had a working communications
control from the beginning.

0 new messages