«

»

Apr
05

Reading Serial Data from Virtual COM Ports

While most desktop developers do not have to deal with Serial COM ports (and I doubt many people miss it), here at Project54 we use COM ports to communicate with a variety of devices (GPS Antennas, Radars, Video Systems, etc.). For anyone that is familiar with programming COM port communication in the Win32 platform, they will most inevitably use the same functions (e.g. CreateFile(), ReadFile()) as outlined here at MSDN.

Like other communication protocols, one has to consider whether to use synchronous or asynchronous communication. With COM ports, asynchronous transmission is defined by using an OVERLAPPED structure and combining it with events to watch out for. For synchronous communication, one would omit the use of the OVERLAPPED structure and will replace it with the use of the COMMTIMEOUT structure (which allow programmers to define the timeout parameters for the ReadFile() and the WriteFile() commands). Most of the time, using this COMMTIMEOUT structure will cause expected timeouts and stop the ReadFile() and the WriteFile() functions from blocking indefinitely. However, there is a case where this is NOT true.

When using Virtual COM Ports, performing synchronous communication will cause the ReadFile() and the WriteFile() to block, regardless of the timeouts you define in the COMMTIMEOUT structure. The workaround to this is to make sure you use the OVERLAPPED structure for asynchronous transmission and define a timeout in a WaitSingleObject(). Below is a piece of example code for asynchronous COM communication.

Also, check out this great resource for serial communication with Visual C++.

OVERLAPPED overlapStruct; // Overlap structure for asynch. serial comm.
memset(&overlapStruct,0,sizeof(overlapStruct)); // Zero out the overlap structure

// Handle used to correlate an event with receiving data at the overlap structure
HANDLE hReadEvent = CreateEvent(NULL,TRUE,FALSE,L”COMRx”);

// Correlate the overlap structure with the event
overlapStruct.hEvent = hReadEvent;

// Number of bytes received by the overlap structure
DWORD bytesRet;

// Buffer for data
char gpsBuffer[1024] = {‘\0′};

// Let’s try open the given COM Port
if ((hComPort =
CreateFile(L”\\\\.\\COM1″, GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL )) == (HANDLE) -1 )
{
// ERROR: Looks like we failed to open the COM Port.
return -1;
}

// Try grab the data from the buffer
ReadFile(hComPort, gpsBuffer, sizeof(gpsBuffer)-1, (LPDWORD)&numRead, &overlapStruct);

// Wait for data to come in through the OVERLAPPED Structure (COM Port)
if(!HasOverlappedIoCompleted(&overlapStruct))
{
// Time-out after 5 seconds if we do nothing has happened with the handle
WaitForSingleObject(hReadEvent,5000);
}

// Let’s check to see if we have a result
int iResult = GetOverlappedResult(hComPort,&overlapStruct,&bytesRet,FALSE);
if( (iResult) && (bytesRet > 0) ){
//
// Got some data from the COM Port
//
}

Mark Taipan

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>