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

Serial i/o problem

190 views
Skip to first unread message

Marcus

unread,
May 14, 2003, 5:39:32 PM5/14/03
to
Hello Experts!

I've been dealing with a serial comm problem for 2 weeks now. The problem is
that ReadFile always return with success even if it read 0 bytes. After 14
bytes ReadFile always return with 0 bytes read. When i debug the program
everything works fine, so it seems like the bytes are read from the buffer
quicker than they arrive. Also, if i check the cbInQue in the Comstat
structure before i launch ReadFile it says 14.
It's strange that ReadFile always success even if it sometimes read 0 bytes.
It even returns successfully when all the bytes are read from the buffer.
How do I know when the transfer is completed ? I could test if bytes
received equals 0, but then the program stops when 14 bytes are read.
Why is ReadFile never pending? Because of this GetOverlappedResult always
returns true. Look at the comments in my code.
After i run PurgeComm to empty the RX-Buffer i have tried to read from the
serial port. ReadFile says 0 bytes are received but the buffer is full of
char number 204 (think it's UNICODE 204).
The article in MSDN on Serial Communication by Allen Denver says that
WaitForSingleObject doesn't occupy the cpu. I strange thing i have noticed
is that the Task Manager in WinXP says it uses 98% of the cpu.
I would also mention that the reading is done in a thread.
I have tried everything I can think of. The DCB is properly set. First I
receive a dcb with GetCommState, then I set the flags. The DCB looks like
this:

// DCB-SETTiNGS
DCB dcb = {0};
if(!GetCommState(hPort, &dcb))
{
failed = true;
}
dcb.DCBlength = sizeof(DCB);
dcb.BaudRate = 57600; // Current baud
dcb.fBinary = TRUE; // Binary mode; no EOF check
dcb.fParity = FALSE; // Disable parity checking.
dcb.fOutxCtsFlow = FALSE; // No CTS output flow control
dcb.fOutxDsrFlow = FALSE; // No DSR output flow control
dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type
dcb.fDsrSensitivity = FALSE; // DSR sensitivity
dcb.fTXContinueOnXoff = FALSE; // XOFF continues Tx
dcb.fOutX = FALSE; // No XON/XOFF out flow control
dcb.fInX = FALSE; // No XON/XOFF in flow control
dcb.fErrorChar = FALSE; // Disable error replacement.
dcb.fNull = FALSE; // Disable null stripping.
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; // RTS flow control
dcb.fAbortOnError = FALSE; // Do not abort reads/writes on
error
dcb.ByteSize = 8; // Number of bits/bytes,
4-8
dcb.Parity = NOPARITY; // 0-4=no,odd,even,mark,space
dcb.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2

I can't use any parity because the device that are connected to the serial
port don't use any parity. I don't know what DTR_CONTROL_ENABLE and
RTS_CONTROL_HANDSHAKE does.

Then i have some more questions. Does WaitForSingleObject wait for all calls
that uses a overlapped structure? For example WaitCommEvent.
If the CommMask is set to EV_RXCHAR, does WaitCommEvent returns true for
every bytes that are received ?

Here are my source for reading:

BOOL fReadCompleted = false;
BOOL bWaiting = false;
GetCommTimeouts(hPort, &CommTimeouts);
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutConstant = 0;
if(!SetCommTimeouts(hPort, &CommTimeouts))
{
// Error setting commtimeouts
return 0;
}

PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
SetupComm(hPort, 32*1024, 32*1024);
if(!SetCommMask(hPort, EV_RXCHAR)
{
// Error setting the CommMask
return 0;
}

if(!WaitCommEvent(hPort, &dwCommMask, &Overlapped))
{
if(GetLastError() == ERROR_IO_PENDING)
{
dwResult = WaitForSingleObject(Overlapped.hEvent, INFINITE);
}
}

while(!fReadCompleted)
{
if (!bWaiting)
{
if (!ReadFile(hPort, &byInByte, 1, &dwBytesReceived, &Overlapped))
{
// Readfile always complete and never goes here
if (GetLastError() != ERROR_IO_PENDING)
{
fReadCompleted = true;
return 1;
}
else
{
// wait for read complete
bWaiting = true;
}
}
else // read successful
{
bWaiting = true;
}
}
if (bWaiting)
{
dwResult = WaitForSingleObject(Overlapped.hEvent, 500);
switch(dwResult)
{
case WAIT_OBJECT_0:
{
// Sometimes ReadFile returns successfully with 0 bytes
read. Why?
// I've tried to check for errors here. EV_ERR occours but
neither of the
// flags CE_OVERRUN, CE_RXPARITY and CE_FRAME is set
// Strange because EV_ERR contains only the three flags.
Correct?
if(GetOverlappedResult(hPort, &Overlapped, &dwBytesReceived,
false))
{
SerialBuffer[nSerialWrite++] = byInByte;
bWaiting = false;
}
else
{
// Never goes here, ReadFile is never pending
fReadCompleted = true;
}
break;
}
case WAIT_TIMEOUT:
{
// Never goes here
fReadCompleted = true;
break;
}
default:
return 1;
}
}
}


Thanks
Marcus


Mark Hansen

unread,
May 14, 2003, 6:24:18 PM5/14/03
to
Marcus wrote:
> Hello Experts!
>
> I've been dealing with a serial comm problem for 2 weeks now. The problem is
> that ReadFile always return with success even if it read 0 bytes. After 14
> bytes ReadFile always return with 0 bytes read. When i debug the program
> everything works fine, so it seems like the bytes are read from the buffer
> quicker than they arrive. Also, if i check the cbInQue in the Comstat
> structure before i launch ReadFile it says 14.
> It's strange that ReadFile always success even if it sometimes read 0 bytes.
> It even returns successfully when all the bytes are read from the buffer.
> How do I know when the transfer is completed ?

Think about this a little bit. What does it mean for the transfer to
be complete? The hardware is connected to some unknown device that
can sit there and spit data down the line any time it wants.

When you perform a read operation, if there are bytes available
(buffered by the driver) they are returned. If no bytes are available
(because you're reading faster than the device is sending data
perhaps?) what do you want to happen? You want the call to fail?

But it didn't fail. If went through its logic, determined that there
was no data to be returned, and told you as much.

Have a look at the ReadFile documentation (which I haven't done,
my comments are from generic use of serial devices via a number
of different languages and protocols) and see what it says it
will do if no data is avaiable.

Some drivers have a way you can tell them to wait for data to
become available before returning. For example, if may be
possible for you to tell the command to return 25 bytes, and
the call can block until 25 bytes have been transfered, then
return them.

Marcus

unread,
May 14, 2003, 7:10:00 PM5/14/03
to

"Mark Hansen" <m...@NOSPAMunify.com> wrote in message
news:b9ugbm$lrg$1@journal...

> Marcus wrote:
> > Hello Experts!
> >
> > I've been dealing with a serial comm problem for 2 weeks now. The
problem is
> > that ReadFile always return with success even if it read 0 bytes. After
14
> > bytes ReadFile always return with 0 bytes read. When i debug the program
> > everything works fine, so it seems like the bytes are read from the
buffer
> > quicker than they arrive. Also, if i check the cbInQue in the Comstat
> > structure before i launch ReadFile it says 14.
> > It's strange that ReadFile always success even if it sometimes read 0
bytes.
> > It even returns successfully when all the bytes are read from the
buffer.
> > How do I know when the transfer is completed ?
>
> Think about this a little bit. What does it mean for the transfer to
> be complete? The hardware is connected to some unknown device that
> can sit there and spit data down the line any time it wants.

I know when the device is sending data. It only sends a file in a stream.
The transfer should be complete when the stream of data (file) has been
transferred (when the receive buffer is empty).

>
> When you perform a read operation, if there are bytes available
> (buffered by the driver) they are returned. If no bytes are available
> (because you're reading faster than the device is sending data
> perhaps?) what do you want to happen? You want the call to fail?

The device runs on the same speed (57600bps). I'm currently using 2 PCs with
a Null-modem cable, so I know that the speed is the same on both ends. The
problem is that the call that is suppose to fail, also fails when 14 bytes
are received.

Mark Hansen

unread,
May 14, 2003, 7:26:57 PM5/14/03
to

I think you've missed my point. The serial device has no concept that
the transfer is finished. It has no way to tell you "the transfer is
finished" because from it's point of view, the remote device could
send more data at any time.

If you know that the remote device has sent more than 14 bytes and
you're just not getting them from the receive buffer, then there
is a different problem happening.

Marcus

unread,
May 14, 2003, 8:34:18 PM5/14/03
to
Hello again!

I forgot one question. If the speed of a port is set to 9600 baud in windows
device manager, can I change it to a higher speed with the DCB structure.
What I mean is, can i use a higher speed than decleared in the control
panel?

/Marcus

"Marcus" <ey...@tiscali.se> wrote in message
news:vvywa.15$4M....@news010.worldonline.se...

Scott McPhillips

unread,
May 15, 2003, 5:04:50 PM5/15/03
to
Marcus wrote:
>
> Hello again!
>
> I forgot one question. If the speed of a port is set to 9600 baud in windows
> device manager, can I change it to a higher speed with the DCB structure.
> What I mean is, can i use a higher speed than decleared in the control
> panel?
>
> /Marcus

Yes. The setting in control panel/device manager is overruled by almost
all serial programs and should not be relied on for anything. Set the
baud rate etc. programmatically to whatever you need.

--
Scott McPhillips [VC++ MVP]

0 new messages