Click here to Skip to main content
15,899,126 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
GeneralRe: (Newbie) Help with doc/view Pin
pba_13-Jul-00 5:47
pba_13-Jul-00 5:47 
QuestionMake copy of DIBSection ? Pin
Christian8-Jul-00 3:23
Christian8-Jul-00 3:23 
GeneralPrinting Dialog Box Pin
etoth17-Jul-00 12:31
etoth17-Jul-00 12:31 
GeneralRe: Printing Dialog Box Pin
Mike Dunn7-Jul-00 17:51
Mike Dunn7-Jul-00 17:51 
GeneralSending the focus back to another window Pin
Mauj7-Jul-00 8:36
Mauj7-Jul-00 8:36 
GeneralRe: Sending the focus back to another window Pin
Yaron8-Jul-00 23:02
Yaron8-Jul-00 23:02 
GeneralRead a single serial byte into COMM-Port Pin
Dieter Wolf7-Jul-00 8:34
sussDieter Wolf7-Jul-00 8:34 
GeneralRe: Read a single serial byte into COMM-Port Pin
Mark Jones19-Jul-00 5:05
Mark Jones19-Jul-00 5:05 
Dieter

Are you using overlapped or non-overlapping i/o on your com port? If you are using overlapped i/o I do have some code which may help you out. I use overlapped i/o because I need simultaneous i/o on multiple COM ports. This is not possible when using non-overlapped i/o, as the relevant WinAPI fns block if two threads try to access them simultaneously.

I have had immense trouble with serial comms myself. Part of the problem I had was getting code that worked both with winNT and win9x - without using conditional compilation. The code below should work with either.

Below is a description of how I deal with serial comms. My code runs in a worker thread which is responsible for comms on one COM port. There are as many worker threads as there are serial devices connected to the PC. The serial devices are typically GSM (cellphone) modems.

I have two functions:

1. UINT CSerialPort::ReadAByte( BYTE &bAcquiredByte)
2. UINT CSerialPort::WaitForCharacter(DWORD dwTimeout)

(BYTE is defined as unsigned char,
DWORD is defined as unsigned long)

ReadAByte() passes back through its bAcquiredByte parameter the byte read in.

The return values that are possible are:

WAIT_OBJECT_0: Byte read in successfully
WAIT_TIMEOUT: No Byte read in
WAIT_FAILED: An error occurred

ReadAByte() calls ::ReadFile() only if there is a byte currently sitting in the incoming byte queue for the COM port. The result of this is that ReadAByte returns immediately with or without a newly acquired byte.

Now when ReadAByte returns WAIT_TIMEOUT what it is really saying is there are no bytes currently in the COM port in queue.

WaitForCharacter() is called with a parameter passed determining timeout in milliseconds.

The return values that are possible are:

WAIT_OBJECT_0: One Byte has arrived at the COM port within the specified timeout.
WAIT_TIMEOUT: No Byte has arrived at the COM Port within the specified timeout.
WAIT_FAILED: An error occurred

Decide on a timeout to use with WaitForCharacter, say 10ms.

To sum up how you would read in a stream of bytes:

1. Call ReadAbyte -
If you get WAIT_OBJECT_0, then a byte has been read in successfully. Call ReadAByte again to get the next byte.
If you get WAIT_TIMEOUT back call WaitForCharacter().

2. If WaitForCharacter() returns WAIT_OBJECT_0, then you're clear to call ReadAByte again (this time there will DEFINITELY be a byte waiting for you).

3. Otherwise, if WaitForCharacter() returns WAIT_TIMEOUT, then no bytes have been received on the port for 10ms.

When you initialise your COM port you need to set the com timeouts and set the comm mask to detect incoming bytes:
(m_hCommPort is the handle to the COM port)

COMMTIMEOUTS TimeOuts = {0,20000,0,0,0 };
::SetCommTimeouts(m_hCommPort, &TimeOuts);
::SetCommMask(m_hCommPort, EV_RXCHAR);

Note that the 20 second timeout ensures that my WaitForCharacter fn times-out before ::ReadFile timesout. (Sometimes I use a timeout value of 10 seconds).

Here's the code, I hope it helps. Remember you will have to change m_hCommPort to whatever your handle name is.

UINT CSerialPort::ReadAByte( BYTE &bAcquiredByte)
{
bAcquiredByte=0;

OVERLAPPED osReader = {0};
osReader.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if (osReader.hEvent == NULL)
return WAIT_FAILED; // error creating event; abort

DWORD dwResult=0; // used to store the return value
// Use ClearCommError to find out number of bytes in buffer
DWORD dwCommErrors;
COMSTAT Status;
ClearCommError(m_hCommPort,&dwCommErrors,&Status);

if (Status.cbInQue==0)
{
dwResult=WAIT_TIMEOUT; // the COM queue for incoming bytes is empty
}
else
{
// Issue read operation for a single byte
DWORD dwReadBytesCount=0;
if (!::ReadFile(m_hCommPort, &bAcquiredByte, 1, &dwReadBytesCount, &osReader))
{
// Note: It appears that ReadFile always returns TRUE.
// I think this is because we do not call ::ReadFile unless we know there is something
// in the com in queue. Also we have a 20 second time out on the port.
dwResult=WAIT_FAILED;
}
else // Read completed immediately
{
if (dwReadBytesCount==1)
dwResult=WAIT_OBJECT_0; // Exactly one byte read in
else
dwResult=WAIT_FAILED;
}
}
CloseHandle(osReader.hEvent);
return dwResult;
}

UINT CSerialPort::WaitForCharacter(DWORD dwTimeout)
{
DWORD dwRes, dwOvRes;
DWORD dwCommEvent=0;
OVERLAPPED osStatus = {0};

osStatus.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if (osStatus.hEvent == NULL)
return WAIT_FAILED; // error creating event; abort

// Issue a status check event
if (!WaitCommEvent(m_hCommPort, &dwCommEvent, &osStatus))
{
if (GetLastError() != ERROR_IO_PENDING)
{
// error in WaitCommEvent; abort
CloseHandle(osStatus.hEvent);
return WAIT_FAILED;
}
else
{
// Still waiting for io, so proceed to waitforsingleobject stage
}
}
else
{
// WaitCommEvent returned immediately - a character has been received!
ASSERT(dwCommEvent==EV_RXCHAR);
CloseHandle(osStatus.hEvent);
return WAIT_OBJECT_0;
}

DWORD dwResult=0;

// Wait dwTimeout milliseconds for an event (ie single char received) to occur.
dwRes = WaitForSingleObject(osStatus.hEvent, dwTimeout);
switch(dwRes)
{
case WAIT_OBJECT_0:
{
if (!GetOverlappedResult(m_hCommPort, &osStatus, &dwOvRes, FALSE))
{
// An error occurred in the overlapped operation;
// call ::GetLastError to find out what it was - if you're interested.
CloseHandle(osStatus.hEvent);
dwResult=WAIT_FAILED;
}
else
{
// Status event is stored in the event flag
// specified in the original WaitCommEvent call.
ASSERT(dwCommEvent==EV_RXCHAR);
CloseHandle(osStatus.hEvent);
dwResult=WAIT_OBJECT_0;
}
break;
}

case WAIT_TIMEOUT:
{
// Wait has timed out.

// Cancel the overlapped io operation - vitally important as closing handle to
// osStatus.hEvent does not do this!!!! If we didn't cancel we'd get
// problems with GetOverlappedResult next time we issued a waitforcharacter.
// Using setcommmask is because of the lack of CancelIo in win95/98.

::SetCommMask(m_hCommPort, EV_RXCHAR); // note this cancels any pending WaitCommEvent

CloseHandle(osStatus.hEvent);
dwResult=WAIT_TIMEOUT;
break;
}
default:
{
// Error in the WaitForSingleObject; abort
// This indicates a problem with the OVERLAPPED structure's
// event handle.

CloseHandle(osStatus.hEvent);
dwResult=WAIT_FAILED;
break;
}
}
return dwResult;
}


GeneralFunction Key usage in Dialog Boxes. Pin
Rick Fishwick7-Jul-00 8:26
sussRick Fishwick7-Jul-00 8:26 
GeneralRe: Function Key usage in Dialog Boxes. Pin
Member 45881447-Jul-00 11:12
Member 45881447-Jul-00 11:12 
GeneralFunction Key usage in Dialog Boxes. Pin
Rick Fishwick7-Jul-00 8:26
sussRick Fishwick7-Jul-00 8:26 
GeneralRe: Function Key usage in Dialog Boxes. Pin
Kurt10-Jul-00 0:00
Kurt10-Jul-00 0:00 
GeneralClass view window for VC++ 6.0 Pin
Kirill Sherman7-Jul-00 7:22
sussKirill Sherman7-Jul-00 7:22 
GeneralRe: Class view window for VC++ 6.0 Pin
Paolo Messina7-Jul-00 8:18
professionalPaolo Messina7-Jul-00 8:18 
GeneralC++ "friend" related Pin
pba_7-Jul-00 7:12
pba_7-Jul-00 7:12 
GeneralRe: C++ Pin
Kirill Sherman7-Jul-00 7:35
sussKirill Sherman7-Jul-00 7:35 
Questionstop MFC re-arranging toolbars when main window re-sized ? Pin
Steve Kearon7-Jul-00 6:12
Steve Kearon7-Jul-00 6:12 
Questionhow i use a wheel message of mouse? Pin
Member 20497-Jul-00 6:03
Member 20497-Jul-00 6:03 
GeneralPassing a CRecordset Pointer to another application through Clipboard Pin
Arvind Wadhawan7-Jul-00 2:55
sussArvind Wadhawan7-Jul-00 2:55 
GeneralRe: Passing a CRecordset Pointer to another application through Clipboard Pin
Pere Mitjavila15-Jul-00 0:07
Pere Mitjavila15-Jul-00 0:07 
GeneralRe: Passing a CRecordset Pointer to another application through Clipboard Pin
Blake Miller15-Jul-00 5:55
Blake Miller15-Jul-00 5:55 
GeneralDevice disabling Pin
cesco7-Jul-00 1:26
cesco7-Jul-00 1:26 
GeneralDoes anyone know how to start with DDK in VC6. Pin
Sajid Siraj6-Jul-00 23:52
Sajid Siraj6-Jul-00 23:52 
QuestionHow can i create an image list independent of the color supported by the system? Pin
Jiju George T6-Jul-00 23:47
Jiju George T6-Jul-00 23:47 
Generalaccess violations Pin
Member 43216-Jul-00 20:08
Member 43216-Jul-00 20:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.