Serial Communication Problem

S

Slobodan Brcin \(eMVP\)

As mentioned in the previous reply post, if 2nd parameter of ReadFile is set
NULL, GetLastError doesn't return ERROR_IO_PENDING.

I do not understand :-(
Second parameter is lpvBuf, right? Why would you like to set it to 0?

I need to see piece of code that you wrote starting from read_os, write_os structure initialization. And that include both readfile
and writefile operations, without any line skipped in between.
I used some free tools that monitor serial port I/O. I could confirm the
output data flow but not input data at all.


Use null cable and second computer to receive text. Then try using WriteFile few times one after another to send some different
data. Look if you will receive in terminal all bytes that you have send. (You will probably have data loss since you did not waited
for transmit to be over, but this is the issue that you have probably not seen yet)

Regards,
Slobodan


George said:
As mentioned in the previous reply post, if 2nd parameter of ReadFile is set
NULL, GetLastError doesn't return ERROR_IO_PENDING.

I modified the code thus,
ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

This code worked well. But the problem is that overlapped operation does not
terminate both WaitCommEvent and ReadFile.

I used some free tools that monitor serial port I/O. I could confirm the
output data flow but not input data at all.
Does this mean that OS input queue does not receive any data from commport?

Slobodan Brcin (eMVP) said:
George,

And my 0.02$ to this:
rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(read_os.hEvent, 1000)) {
dwBytesRead = 0;
} else {
rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
if (rc) {
read_os.Offset = dwBytesRead;
}
}
} else {
read_os.Offset = dwBytesRead;
}

There is no offset value on pipes and serial drivers. (What would offset mean in a continuous stream without beginning and the end
to the driver)

To reduce confusion to yourself instead of:
rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
Use:
rc = ReadFile(hComm, lpvBuf, cbRead, 0, &read_os);

dwBytesRead in overlapped case has no meaning.

WaitForSingleObject do not use this, especially not in test sample.
Also use GetOverlappedResult with TRUE.

For instance following should work instead of your code above:

ReadFile(hComm, lpvBuf, cbRead, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

Regards,
Slobodan


KM said:
George,

Not going deeply in to the code, a couple of glitches:

- If you open file with FILE_FLAG_OVERLAPPED, you must set the last parameter of the WaitCommEvent to not NULL and pass a
manual-reset event object.
You have, however, this: WaitCommEvent(nComID, &dwEvtMask, NULL);
Please see the msdn sample the link to I posted in some previous reply in this thread.

- For debugging purposes make your code single threading. That may be easy if instead of CreateThread(..., CommPortMonitor,...)
you just call CommPortMonitor.

KM

This is the part of my application that regards to commport communication.
Wait CommEvent thread loop terminates only when application terminated or
fContinue flag turned into ON.
WriteFile() goes well without any problem and the device connected works as
designed.
The device returns correct data for the command sent from my application.
But WaitCommEvent() never returns though the data sent from the device
correctly arrive at the comport.

/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
HANDLE nComID;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);


//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, "COM1:9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);


/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
return -1;
}

if (ThreadHdl == NULL) {
ThreadHdl = CreateThread(NULL, 0, CommPortMonitor,
this, CREATE_SUSPENDED, &ThreadID);
if (ThreadHdl == NULL) {
return -1;
}
ResumeThread(ThreadHdl);
}

return 0;
}

/***********************************************************************************************
***********************************Wait CommEvent
Thread*****************************************
************************************************************************************************/
extern "C"
DWORD __stdcall CommPortMonitor( void* pparam )
{
DWORD dwEvtMask; // kind of communication event(set in
WaitCommEvent())
DWORD dwError;
COMSTAT ComStat; // status of communication port(set in
ClearCommClear())
BOOL bRet;
int nReadCnt; // bytes received(return value of ReadComPort())

bSetMask = SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while (TRUE) {
bRet = WaitCommEvent(nComID, &dwEvtMask, NULL);
if (!fContinue) {
break;
}
ClearCommError(nComID, &dwError, &ComStat);
if (!bRet) {
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
continue;
}
}

if (dwEvtMask & EV_ERR) { // CE_FRAME, CE_OVERRUN, CE_RXPARITY
//error-handling
continue;
}

if (ComStat.cbInQue > 0) { // check existence of receive data
ReadComPort(nComID, byBuffer, 1024);
//data-handling
}
}

return TRUE;
}

/***********************************************************************************************
*****************************************Read
Data***********************************************
************************************************************************************************/
int HWPIN::ReadComPort(HANDLE hComm, void* lpvBuf, int cbRead)
{
DWORD dwError;
COMSTAT comstat;

BOOL bContinue = TRUE;
DWORD dwBytesRead = 0;
BOOL rc = 0;

read_os.Offset = 0;

rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(read_os.hEvent, 1000)) {
dwBytesRead = 0;
} else {
rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
if (rc) {
read_os.Offset = dwBytesRead;
}
}
} else {
read_os.Offset = dwBytesRead;
}

if (rc) {
return read_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}

/***********************************************************************************************
****************************************Write
Data**********************************************
************************************************************************************************/
int HWPIN::WriteComPort(HANDLE hComm, const void* lpvBuf, int cbWrite)
{
DWORD dwError;
COMSTAT comstat;
DWORD dwBytesWritten = 0;
BOOL rc = 0;

write_os.Offset = 0;

rc = WriteFile(hComm, lpvBuf, cbWrite, &dwBytesWritten, &write_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(write_os.hEvent, 1000)) {
dwBytesWritten = 0 ;
} else {
rc = GetOverlappedResult( nComID,
&write_os,
&dwBytesWritten, FALSE);
if (rc) {
write_os.Offset = dwBytesWritten;
}
}
} else {
write_os.Offset = dwBytesWritten;
}

if (rc) {
return write_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}


:

Hi George,

No matter what SetumComm settings that you use (default) serial driver should work.
You have a logic error in your code regarding when you expect to get some data.

Post here complete segment starting with readfile and explain what do you expect to get with each next API call. (This is few
lines
that you should try to explain to your-self, but doing that "aloud" ca usually help)

Regards,
Slobodan

I tested with a simple application in a simple condition.
Connect 2 PCs with serial cable and run above application on both PC.

Everything went well all around.
The data packet sent from 1 PC could be correctly received by another PC.
If some character data is reached to the system receive buffer,
WaitCommEvent is terminated and ReadFile correctly read buffer data.
According to this result, I think the receive data logic is not wrong.
Some field of DCB structure, 2nd parameter of SetCommState, may be wrong for
my appllication or device (or XP Embedded component configuration).

By the way, I found the API SetupComm. Is this API necessary for our
application?

:

George,

Somehow I seem to overlook your reply in this thread.

HasOverlappedIoCompleted returns FALSE.

Yup. This is what we expected, right?
It would be worse if it returned TRUE while GetOverlappedResult returned 0 bytes transferred.

By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
FALSE. Why?

How about checking with GetLastError?

Any 2nd parameter of SetCommMask() results in the same.

Please look at this MSDN sample code to see how it should work in a simple case:
http://msdn.microsoft.com/library/en-us/devio/base/monitoring_communications_events.asp

Your problem does not seem to be related to XPe. You would better off developing, texting and debugging the app on XP Pro
first
and
then move to XPe.
As Slobodan mentioned you can get more help if you open more sources and post in more appropriate NG.

Regards,
KM

:

Just to add to that..

George, look at the HasOverlappedIoCompleted macro to see if it can help to determine the completion of an outstanding
I/O
operation.

--
Regards,
KM, BSquare Corp.


Hi George,

One basic question do you know how overlapped operation are working?

You should choose between one of two following syntaxes.
ReadFile(ComID, lpvBuf, nRead, 0, &read); -----> For overlapped access
ReadFile(ComID, lpvBuf, nRead, &BytesRead, 0); ---> For regular access.

Using both values with overlapped access does not make sense since all operations will return immediately and set
BytesRead to
0
or
some unknown value that represent some data that was already available in internal OS buffers, depending on
driver
that
you
use.
But
this length info is usually 0 (treat is as undefined).

Length info is filled only during the IO API call not later.
So only way for you to obtain current results of overlapped operation is to read overlapped structure directly or use
API
functions
like GetOverlappedResult.

Also all operations on buffer are not synchronous but rather asynchronous. This mean that you can issue few different
read
and
write
operations on different handles and still execute some other code while drivers and hardware gather your data.

Regards,
Slobodan


Depend on queue status? What's that?

Yes, I tried to GetOverlappedResult() with 3rd parameter TRUE, but no
difference.
GetOverlappedResult() returns successfully but "BytesRead" is always 0.


:

Hi George,

I have not tested another OS than Windows XP Embedded.
Does OS matter about this phenomenon?

Not really, but this NG is less apropriate for this type (API programmming type) of questions. And one SDK/DDK
related
would
be
better for obtaining answers on these topics. When you have something tha twork on XP Pro and do not work on XPe
then
this
is
NG
to
ask for help.

OK I'll try to make test program without sub-thread and set timeout properly.

R/W file operation is simple as below. This operation is done after (10)'s
check.
ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);

With overlapped structured BytesRead, BytesWritten usually do not contain values that you expect and they will be
most
likely
0
(depending on queue status).

Wait for completion of overlapped operaion.
GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);

Since both read and write are overlapped, please use GetOverlappedResults to wait for operation to complete after
both
read
and
write operations. Ase last parameter as TRUE for test cases.

Check if "BytesWritten" is over zero, and application specific process.

I also tried without using WaitCommEvent but only ReadFile within eternal
while loop, but the result was same. No data could be read.

What is wrong?

Probably you do not wait to receive data with GetOverlappedResult. (Without complete code I can't tell for sure).

BIOS level setting?
NO. Has nothing to do with this.
OS setting?
NO, since you configure DCB, timeouts etc.

Shortage of pre-configuration in my application?
NO. You have configured all that is needed. But set timeouts (if you want them, for test they are not important)

Regards,
Slobodan


:

Hi George,

Does this work on XP Pro?

Why do you create new thread for simple test? Simplify your test case.
Always use timeouts for receive operation. (Unless you want your program to stuck if there is not enough data
requested by
read
operation).
Either SetCommMask or WaitCommEvent caused problems for me long time ago so I do not use them.(There is
no
need
for
them
especially
since you use overlapped access).
Where are read and write file in your example?

Regards,
Slobodan

Hi.
Please give me some advise.
I want to communicate with a device via COM port and coded typical
communication program using Windows SDK.

The program sequence is thus...
(1) CreateFile with overlap mode.
ComID = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

(2) BuildCommDCB
BuildCommDCB("COM1",&dcb);

(3) SetCommState with some parameter set by the value the device requires
and others by default.
SetCommState(ComID, &dcb);

(4) SetCommTimeouts with no timeout.
SetCommTimeouts(ComID, &comm_timeout);

(5) SetCommMask
SetCommMask(ComID, EV_RXCHAR);

(6) CreateThread.

(7) In the thread created above, WaitCommEvent for a data sent from the
device.
WaitCommEvent(ComID, &EventMask, &event);

(8) Wait until the overlapped operation complete.
GetOverlappedResult(ComID, &event, &Transfer, TRUE);

(9) Get error code and clear.
ClearCommError(ComID, &Error, &ComStat);

(10) Check the receive queue if some data is received.

The problem is that function WaitCommEvent never return!
Instead of WaitCommEvent, I tried to ReadFile(COM1) directly in while loop,
but the loop never ended.

I confirmed that the command from application to the device is correctly sent.
And also confirmed by line monitor connected between the device and COM port
that the device returns correct response for the command sent by my
application.
But why my application can't receive any data?
Almost all the settings are set by general value.

OS is Windows XP Embedded with almost full functionality configuration.

Please help me. Thanks.
 
K

KM

George,

This is going to be hard to help with the issue if you only post a piece of code.
You would need to show us the code where and how you define and initialize all the structures used.

Also, to debug the issue you seem to run the code under debugger. Is this true?
I would recommend you to use debug output instead. Use OutputDebugString API and have it called with some useful info after every
single important line in your code.
Then when you post the code here you would also need to post the debug output. This way we can understand what is going on your
device.

--
Regards,
KM, BSquare Corp.

I modified the program regarding to WaitCommEvent as following.
If the 2nd parameter of WaitCommEvent() is set NULL, GetLastError() doesn't
return ERROR_IO_PENDING.

GetOverlappedResult() function never terminates though line monitor catches
the char data sent from the device to the commport.

----------------------------------------------------------------------------------------------------
SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while(TRUE){
bRet = WaitCommEvent(nComID, &dwEvtMask, &event_os);
unsigned long ulError = GetLastError();
if (!bRet && ulError == ERROR_IO_PENDING){
dwRes = WaitForSingleObject(event_os.hEvent, INFINITE); // wait
infinitely until the data is put into input queue
switch(dwRes)
{
// Event occurred.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(nComID, &event_os,
&dwTransfer, FALSE))
continue;
else
ClearCommError(nComID, &dwError, &ComStat);
break;
case WAIT_TIMEOUT:
continue;
default:
// Error in the WaitForSingleObject; abort
// This indicates a problem with the OVERLAPPED
structure's
// event handle.
CloseHandle(event_os.hEvent);
return FALSE;
}
}

// application specific input-data processing

}


KM said:
George,

Not going deeply in to the code, a couple of glitches:

- If you open file with FILE_FLAG_OVERLAPPED, you must set the last parameter of the WaitCommEvent to not NULL and pass a
manual-reset event object.
You have, however, this: WaitCommEvent(nComID, &dwEvtMask, NULL);
Please see the msdn sample the link to I posted in some previous reply in this thread.

- For debugging purposes make your code single threading. That may be easy if instead of CreateThread(..., CommPortMonitor,...)
you just call CommPortMonitor.

KM
This is the part of my application that regards to commport communication.
Wait CommEvent thread loop terminates only when application terminated or
fContinue flag turned into ON.
WriteFile() goes well without any problem and the device connected works as
designed.
The device returns correct data for the command sent from my application.
But WaitCommEvent() never returns though the data sent from the device
correctly arrive at the comport.

/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
HANDLE nComID;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile("COM1",
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);


//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, "COM1:9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);


/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
return -1;
}

if (ThreadHdl == NULL) {
ThreadHdl = CreateThread(NULL, 0, CommPortMonitor,
this, CREATE_SUSPENDED, &ThreadID);
if (ThreadHdl == NULL) {
return -1;
}
ResumeThread(ThreadHdl);
}

return 0;
}

/***********************************************************************************************
***********************************Wait CommEvent
Thread*****************************************
************************************************************************************************/
extern "C"
DWORD __stdcall CommPortMonitor( void* pparam )
{
DWORD dwEvtMask; // kind of communication event(set in
WaitCommEvent())
DWORD dwError;
COMSTAT ComStat; // status of communication port(set in
ClearCommClear())
BOOL bRet;
int nReadCnt; // bytes received(return value of ReadComPort())

bSetMask = SetCommMask(nComID, EV_RXCHAR | EV_ERR);

while (TRUE) {
bRet = WaitCommEvent(nComID, &dwEvtMask, NULL);
if (!fContinue) {
break;
}
ClearCommError(nComID, &dwError, &ComStat);
if (!bRet) {
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
continue;
}
}

if (dwEvtMask & EV_ERR) { // CE_FRAME, CE_OVERRUN, CE_RXPARITY
//error-handling
continue;
}

if (ComStat.cbInQue > 0) { // check existence of receive data
ReadComPort(nComID, byBuffer, 1024);
//data-handling
}
}

return TRUE;
}

/***********************************************************************************************
*****************************************Read
Data***********************************************
************************************************************************************************/
int HWPIN::ReadComPort(HANDLE hComm, void* lpvBuf, int cbRead)
{
DWORD dwError;
COMSTAT comstat;

BOOL bContinue = TRUE;
DWORD dwBytesRead = 0;
BOOL rc = 0;

read_os.Offset = 0;

rc = ReadFile(hComm, lpvBuf, cbRead, &dwBytesRead, &read_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(read_os.hEvent, 1000)) {
dwBytesRead = 0;
} else {
rc = GetOverlappedResult(nComID, &read_os, &dwBytesRead, FALSE);
if (rc) {
read_os.Offset = dwBytesRead;
}
}
} else {
read_os.Offset = dwBytesRead;
}

if (rc) {
return read_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}

/***********************************************************************************************
****************************************Write
Data**********************************************
************************************************************************************************/
int HWPIN::WriteComPort(HANDLE hComm, const void* lpvBuf, int cbWrite)
{
DWORD dwError;
COMSTAT comstat;
DWORD dwBytesWritten = 0;
BOOL rc = 0;

write_os.Offset = 0;

rc = WriteFile(hComm, lpvBuf, cbWrite, &dwBytesWritten, &write_os);
if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
if (WaitForSingleObject(write_os.hEvent, 1000)) {
dwBytesWritten = 0 ;
} else {
rc = GetOverlappedResult( nComID,
&write_os,
&dwBytesWritten, FALSE);
if (rc) {
write_os.Offset = dwBytesWritten;
}
}
} else {
write_os.Offset = dwBytesWritten;
}

if (rc) {
return write_os.Offset;
} else {
// error handling
PurgeComm(nComID, PURGE_TXABORT | PURGE_RXABORT);
ClearCommError(nComID, &dwError, &comstat);
return -1;
}
}


:

Hi George,

No matter what SetumComm settings that you use (default) serial driver should work.
You have a logic error in your code regarding when you expect to get some data.

Post here complete segment starting with readfile and explain what do you expect to get with each next API call. (This is few
lines
that you should try to explain to your-self, but doing that "aloud" ca usually help)

Regards,
Slobodan

I tested with a simple application in a simple condition.
Connect 2 PCs with serial cable and run above application on both PC.

Everything went well all around.
The data packet sent from 1 PC could be correctly received by another PC.
If some character data is reached to the system receive buffer,
WaitCommEvent is terminated and ReadFile correctly read buffer data.
According to this result, I think the receive data logic is not wrong.
Some field of DCB structure, 2nd parameter of SetCommState, may be wrong for
my appllication or device (or XP Embedded component configuration).

By the way, I found the API SetupComm. Is this API necessary for our
application?

:

George,

Somehow I seem to overlook your reply in this thread.

HasOverlappedIoCompleted returns FALSE.

Yup. This is what we expected, right?
It would be worse if it returned TRUE while GetOverlappedResult returned 0 bytes transferred.

By the way, just after SetCommMask() returns TRUE, GetCommMask() returns
FALSE. Why?

How about checking with GetLastError?

Any 2nd parameter of SetCommMask() results in the same.

Please look at this MSDN sample code to see how it should work in a simple case:
http://msdn.microsoft.com/library/en-us/devio/base/monitoring_communications_events.asp

Your problem does not seem to be related to XPe. You would better off developing, texting and debugging the app on XP Pro
first
and
then move to XPe.
As Slobodan mentioned you can get more help if you open more sources and post in more appropriate NG.

Regards,
KM

:

Just to add to that..

George, look at the HasOverlappedIoCompleted macro to see if it can help to determine the completion of an outstanding
I/O
operation.

--
Regards,
KM, BSquare Corp.


Hi George,

One basic question do you know how overlapped operation are working?

You should choose between one of two following syntaxes.
ReadFile(ComID, lpvBuf, nRead, 0, &read); -----> For overlapped access
ReadFile(ComID, lpvBuf, nRead, &BytesRead, 0); ---> For regular access.

Using both values with overlapped access does not make sense since all operations will return immediately and set
BytesRead to
0
or
some unknown value that represent some data that was already available in internal OS buffers, depending on driver that
you
use.
But
this length info is usually 0 (treat is as undefined).

Length info is filled only during the IO API call not later.
So only way for you to obtain current results of overlapped operation is to read overlapped structure directly or use
API
functions
like GetOverlappedResult.

Also all operations on buffer are not synchronous but rather asynchronous. This mean that you can issue few different
read
and
write
operations on different handles and still execute some other code while drivers and hardware gather your data.

Regards,
Slobodan


Depend on queue status? What's that?

Yes, I tried to GetOverlappedResult() with 3rd parameter TRUE, but no
difference.
GetOverlappedResult() returns successfully but "BytesRead" is always 0.


:

Hi George,

I have not tested another OS than Windows XP Embedded.
Does OS matter about this phenomenon?

Not really, but this NG is less apropriate for this type (API programmming type) of questions. And one SDK/DDK
related
would
be
better for obtaining answers on these topics. When you have something tha twork on XP Pro and do not work on XPe
then
this
is
NG
to
ask for help.

OK I'll try to make test program without sub-thread and set timeout properly.

R/W file operation is simple as below. This operation is done after (10)'s
check.
ReadFile(ComID, lpvBuf, nRead, &BytesRead, &read);
WriteFile(ComID, lpvBuf, nWrite, &BytesWritten, &write);

With overlapped structured BytesRead, BytesWritten usually do not contain values that you expect and they will be
most
likely
0
(depending on queue status).

Wait for completion of overlapped operaion.
GetOverlappedResult(ComID, &write, &BytesWritten, FALSE);

Since both read and write are overlapped, please use GetOverlappedResults to wait for operation to complete after
both
read
and
write operations. Ase last parameter as TRUE for test cases.

Check if "BytesWritten" is over zero, and application specific process.

I also tried without using WaitCommEvent but only ReadFile within eternal
while loop, but the result was same. No data could be read.

What is wrong?

Probably you do not wait to receive data with GetOverlappedResult. (Without complete code I can't tell for sure).

BIOS level setting?
NO. Has nothing to do with this.
OS setting?
NO, since you configure DCB, timeouts etc.

Shortage of pre-configuration in my application?
NO. You have configured all that is needed. But set timeouts (if you want them, for test they are not important)

Regards,
Slobodan


:

Hi George,

Does this work on XP Pro?

Why do you create new thread for simple test? Simplify your test case.
Always use timeouts for receive operation. (Unless you want your program to stuck if there is not enough data
requested by
read
operation).
Either SetCommMask or WaitCommEvent caused problems for me long time ago so I do not use them.(There is no need
for
them
especially
since you use overlapped access).
Where are read and write file in your example?

Regards,
Slobodan

Hi.
Please give me some advise.
I want to communicate with a device via COM port and coded typical
communication program using Windows SDK.

The program sequence is thus...
(1) CreateFile with overlap mode.
ComID = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

(2) BuildCommDCB
BuildCommDCB("COM1",&dcb);

(3) SetCommState with some parameter set by the value the device requires
and others by default.
SetCommState(ComID, &dcb);

(4) SetCommTimeouts with no timeout.
SetCommTimeouts(ComID, &comm_timeout);

(5) SetCommMask
SetCommMask(ComID, EV_RXCHAR);

(6) CreateThread.

(7) In the thread created above, WaitCommEvent for a data sent from the
device.
WaitCommEvent(ComID, &EventMask, &event);

(8) Wait until the overlapped operation complete.
GetOverlappedResult(ComID, &event, &Transfer, TRUE);

(9) Get error code and clear.
ClearCommError(ComID, &Error, &ComStat);

(10) Check the receive queue if some data is received.

The problem is that function WaitCommEvent never return!
Instead of WaitCommEvent, I tried to ReadFile(COM1) directly in while loop,
but the loop never ended.

I confirmed that the command from application to the device is correctly sent.
And also confirmed by line monitor connected between the device and COM port
that the device returns correct response for the command sent by my
application.
But why my application can't receive any data?
Almost all the settings are set by general value.

OS is Windows XP Embedded with almost full functionality configuration.

Please help me. Thanks.
 
G

Guest

There was an information that I was forgetting to tell.
The serial cable that I use to connect the device in question has some
specific feature.
In general, serial cable with 9 pins has 8 signal lines and 1 ground line.
But my cable uses only 3 signal lines, RxD/TxD/CTS. Other signal lines are
not used.
Will this affect the serial communication?
 
S

Slobodan Brcin \(eMVP\)

Hi George,
Will this affect the serial communication?
Yes and No.
3 Wires are more than enough for full duplex communication, but you must tell serial driver and hardware not to use things like DTR,
RTS, CTS, etc signals by properly configuring DCB structure.

Also one thing from your DCB structure than I have seen now is byte size 7 bits and 2 stop bits, why this?

Regards,
Slobodan
 
G

Guest

DCB settings...

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;

Is this all that relates to the signal lines?
Any other settings than DCB configuring?

Why byte size 7 bits and 2 stop bits?
Data type in communication is all ascii character.
 
G

Guest

Sorry for annoying you by my many misunderstandings.
I'll post the full source code of the sample console program that only send
and receive simple character data.


/////////////////////////////////////////////////////////////Start Of
Source////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "windows.h"

HANDLE hWnd;
HANDLE nComID;
OVERLAPPED read_os;
OVERLAPPED write_os;

BYTE byBuffer[1024];

void Initialize();
long OpenCommPort();
long CloseCommPort();

int main(int argc, char* argv[])
{

char cSel[2];
DWORD dwBytesWritten;
DWORD dwBytesRead;

Initialize();

if(OpenCommPort() == -1){
printf("OpenCommPort Error.\n");
return 1;
}

do{
printf("Select operation. R:Read, W:Write, Q:Quit -> ");
scanf(" %c", &cSel[0]);

if(cSel[0] == 'W' || cSel[0] == 'w' ){
WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);
}

if(cSel[0] == 'R' || cSel[0] == 'r' ){
ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

if(dwBytesRead != 0){
printf("received data = ");
for(unsigned int i=0; i < dwBytesRead ; i++){
putchar(byBuffer);
}
printf("\n");
}else{
printf("No data.\n");
}
Sleep(100);
}

if(cSel[0] == 'Q' || cSel[0] == 'q' ){
break;
}

}while(TRUE);

CloseCommPort();
return 0;
}

/**********************************************************************************************
*******************************************Initialization****************************************
************************************************************************************************/
void Initialize(){
nComID = INVALID_HANDLE_VALUE;

memset(&write_os, 0, sizeof(OVERLAPPED));
memset(&read_os, 0, sizeof(OVERLAPPED));

read_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name
write_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name

}


/***********************************************************************************************
*******************************************Open
ComPort****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];
char cPortNum[2];
char cPort[5];

printf("Com Port No? -> ");
scanf(" %c", &cPortNum[0]);

if(cPortNum[0] == '1'){
memcpy(cPort, "COM1", 4);
}else if(cPortNum[0] == '2'){
memcpy(cPort, "COM2", 4);
}else if(cPortNum[0] == '3'){
memcpy(cPort, "COM3", 4);
}else if(cPortNum[0] == '4'){
memcpy(cPort, "COM4", 4);
}else{
return -1;
}

cPort[4] = NULL;

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile(cPort,
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

if(nComID == INVALID_HANDLE_VALUE){
printf("CreateFile Error.\n");
return -1;
}
printf("CreateFile\n");

//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, cPort);
strcat(szPortSet, ":9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);

if(bBuildComm == FALSE){
printf("BuildCommDCB Error.\n");
return -1;
}
printf("BuildCommDCB\n");


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);

if(bSetCommStateRtn == FALSE){
printf("SetCommState Error.\n");
return -1;
}
printf("SetCommState\n");

/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
printf("SetCommTimeouts Error.\n");
return -1;
}
printf("SetCommTimeouts\n");

return 0;
}

/***********************************************************************************************
*******************************************Close
ComPort*****************************************
************************************************************************************************/
long CloseCommPort(){
CloseHandle(nComID);
return 0;

}

/////////////////////////////////////////////////////////////End Of
Source////////////////////////////////////////////////////////////////////////
 
S

Slobodan Brcin \(eMVP\)

Hi George,
Why byte size 7 bits and 2 stop bits?
Data type in communication is all ascii character.

Are you sure that your device hardware is set in this way, also?

Sorry if I already asked this but I can't remember. Are you using RS-485 or RS-232 interface?

Regards,
Slobodan
 
S

Slobodan Brcin \(eMVP\)

Hi George,

What happens in this code?
If it get stuck on GetOverlappedResults then it is expected behavior.

You told to read command to wait for 1024 characters and not for 1. And at the same time you are using infinite timeouts so read
will never end. (Well it will if you receive 1024 characters)
ReadFile(nComID, byBuffer, 1024, 0, &read_os);

Switch count to 1. And if this does not work use HyperTerminal to test your connection and let us know if that helped.

Regards,
Slobodan





George said:
Sorry for annoying you by my many misunderstandings.
I'll post the full source code of the sample console program that only send
and receive simple character data.


/////////////////////////////////////////////////////////////Start Of
Source////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "windows.h"

HANDLE hWnd;
HANDLE nComID;
OVERLAPPED read_os;
OVERLAPPED write_os;

BYTE byBuffer[1024];

void Initialize();
long OpenCommPort();
long CloseCommPort();

int main(int argc, char* argv[])
{

char cSel[2];
DWORD dwBytesWritten;
DWORD dwBytesRead;

Initialize();

if(OpenCommPort() == -1){
printf("OpenCommPort Error.\n");
return 1;
}

do{
printf("Select operation. R:Read, W:Write, Q:Quit -> ");
scanf(" %c", &cSel[0]);

if(cSel[0] == 'W' || cSel[0] == 'w' ){
WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);
}

if(cSel[0] == 'R' || cSel[0] == 'r' ){
ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

if(dwBytesRead != 0){
printf("received data = ");
for(unsigned int i=0; i < dwBytesRead ; i++){
putchar(byBuffer);
}
printf("\n");
}else{
printf("No data.\n");
}
Sleep(100);
}

if(cSel[0] == 'Q' || cSel[0] == 'q' ){
break;
}

}while(TRUE);

CloseCommPort();
return 0;
}

/***********************************************************************************************
*******************************************Initialization*****************************************
************************************************************************************************/
void Initialize(){
nComID = INVALID_HANDLE_VALUE;

memset(&write_os, 0, sizeof(OVERLAPPED));
memset(&read_os, 0, sizeof(OVERLAPPED));

read_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name
write_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name

}


/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];
char cPortNum[2];
char cPort[5];

printf("Com Port No? -> ");
scanf(" %c", &cPortNum[0]);

if(cPortNum[0] == '1'){
memcpy(cPort, "COM1", 4);
}else if(cPortNum[0] == '2'){
memcpy(cPort, "COM2", 4);
}else if(cPortNum[0] == '3'){
memcpy(cPort, "COM3", 4);
}else if(cPortNum[0] == '4'){
memcpy(cPort, "COM4", 4);
}else{
return -1;
}

cPort[4] = NULL;

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile(cPort,
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

if(nComID == INVALID_HANDLE_VALUE){
printf("CreateFile Error.\n");
return -1;
}
printf("CreateFile\n");

//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, cPort);
strcat(szPortSet, ":9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);

if(bBuildComm == FALSE){
printf("BuildCommDCB Error.\n");
return -1;
}
printf("BuildCommDCB\n");


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);

if(bSetCommStateRtn == FALSE){
printf("SetCommState Error.\n");
return -1;
}
printf("SetCommState\n");

/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
printf("SetCommTimeouts Error.\n");
return -1;
}
printf("SetCommTimeouts\n");

return 0;
}

/***********************************************************************************************
*******************************************Close
ComPort*****************************************
************************************************************************************************/
long CloseCommPort(){
CloseHandle(nComID);
return 0;

}

/////////////////////////////////////////////////////////////End Of
Source////////////////////////////////////////////////////////////////////////

Slobodan Brcin (eMVP) said:
I do not understand :-(
Second parameter is lpvBuf, right? Why would you like to set it to 0?

I need to see piece of code that you wrote starting from read_os, write_os structure initialization. And that include both readfile
and writefile operations, without any line skipped in between.



Use null cable and second computer to receive text. Then try using WriteFile few times one after another to send some different
data. Look if you will receive in terminal all bytes that you have send. (You will probably have data loss since you did not waited
for transmit to be over, but this is the issue that you have probably not seen yet)

Regards,
Slobodan
 
G

Guest

Yes. As I mentioned before, the line monitor receives correct data sent from
the device.
Actual data character and control char such as ACK/STX/ETX are captured by
monitor and they are just expected data.
This means that the setting of baud rate, data byte, stop bits, parity, etc
is suitable for the device, doesn't it?

Serial I/F is general RS-232. Except of some signal line shortage, I think
there's no specific feature in my system.
 
S

Slobodan Brcin \(eMVP\)

Hi George,
This means that the setting of baud rate, data byte, stop bits, parity, etc
is suitable for the device, doesn't it?

Right.

Regards,
Slobodan

PS: Look in another sub-thread for more info.
 
G

Guest

Slobodan,
ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

Though character data is sent to commport, "dwBytesRead" is always 0 and the
data is not stacked in "byBuffer".
WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);

This works successfully. "dwBytesWritten" is always 9.


George

Slobodan Brcin (eMVP) said:
Hi George,

What happens in this code?
If it get stuck on GetOverlappedResults then it is expected behavior.

You told to read command to wait for 1024 characters and not for 1. And at the same time you are using infinite timeouts so read
will never end. (Well it will if you receive 1024 characters)
ReadFile(nComID, byBuffer, 1024, 0, &read_os);

Switch count to 1. And if this does not work use HyperTerminal to test your connection and let us know if that helped.

Regards,
Slobodan





George said:
Sorry for annoying you by my many misunderstandings.
I'll post the full source code of the sample console program that only send
and receive simple character data.


/////////////////////////////////////////////////////////////Start Of
Source////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "windows.h"

HANDLE hWnd;
HANDLE nComID;
OVERLAPPED read_os;
OVERLAPPED write_os;

BYTE byBuffer[1024];

void Initialize();
long OpenCommPort();
long CloseCommPort();

int main(int argc, char* argv[])
{

char cSel[2];
DWORD dwBytesWritten;
DWORD dwBytesRead;

Initialize();

if(OpenCommPort() == -1){
printf("OpenCommPort Error.\n");
return 1;
}

do{
printf("Select operation. R:Read, W:Write, Q:Quit -> ");
scanf(" %c", &cSel[0]);

if(cSel[0] == 'W' || cSel[0] == 'w' ){
WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);
}

if(cSel[0] == 'R' || cSel[0] == 'r' ){
ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

if(dwBytesRead != 0){
printf("received data = ");
for(unsigned int i=0; i < dwBytesRead ; i++){
putchar(byBuffer);
}
printf("\n");
}else{
printf("No data.\n");
}
Sleep(100);
}

if(cSel[0] == 'Q' || cSel[0] == 'q' ){
break;
}

}while(TRUE);

CloseCommPort();
return 0;
}

/***********************************************************************************************
*******************************************Initialization*****************************************
************************************************************************************************/
void Initialize(){
nComID = INVALID_HANDLE_VALUE;

memset(&write_os, 0, sizeof(OVERLAPPED));
memset(&read_os, 0, sizeof(OVERLAPPED));

read_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name
write_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name

}


/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];
char cPortNum[2];
char cPort[5];

printf("Com Port No? -> ");
scanf(" %c", &cPortNum[0]);

if(cPortNum[0] == '1'){
memcpy(cPort, "COM1", 4);
}else if(cPortNum[0] == '2'){
memcpy(cPort, "COM2", 4);
}else if(cPortNum[0] == '3'){
memcpy(cPort, "COM3", 4);
}else if(cPortNum[0] == '4'){
memcpy(cPort, "COM4", 4);
}else{
return -1;
}

cPort[4] = NULL;

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile(cPort,
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

if(nComID == INVALID_HANDLE_VALUE){
printf("CreateFile Error.\n");
return -1;
}
printf("CreateFile\n");

//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, cPort);
strcat(szPortSet, ":9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);

if(bBuildComm == FALSE){
printf("BuildCommDCB Error.\n");
return -1;
}
printf("BuildCommDCB\n");


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);

if(bSetCommStateRtn == FALSE){
printf("SetCommState Error.\n");
return -1;
}
printf("SetCommState\n");

/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
printf("SetCommTimeouts Error.\n");
return -1;
}
printf("SetCommTimeouts\n");

return 0;
}

/***********************************************************************************************
*******************************************Close
ComPort*****************************************
************************************************************************************************/
long CloseCommPort(){
CloseHandle(nComID);
return 0;

}

/////////////////////////////////////////////////////////////End Of
Source////////////////////////////////////////////////////////////////////////

Slobodan Brcin (eMVP) said:
As mentioned in the previous reply post, if 2nd parameter of ReadFile is set
NULL, GetLastError doesn't return ERROR_IO_PENDING.

I do not understand :-(
Second parameter is lpvBuf, right? Why would you like to set it to 0?

I need to see piece of code that you wrote starting from read_os, write_os structure initialization. And that include both readfile
and writefile operations, without any line skipped in between.

I used some free tools that monitor serial port I/O. I could confirm the
output data flow but not input data at all.


Use null cable and second computer to receive text. Then try using WriteFile few times one after another to send some different
data. Look if you will receive in terminal all bytes that you have send. (You will probably have data loss since you did not waited
for transmit to be over, but this is the issue that you have probably not seen yet)

Regards,
Slobodan

 
S

Slobodan Brcin \(eMVP\)

Hi George,

I have lost you, and what problem you currently have, please read following and give me explanation of what is that you see that is
happening.


Following is from Platform SDK:
COMMTIMEOUTS: ReadIntervalTimeout, A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant and
ReadTotalTimeoutMultiplier members, specifies that the read operation is to return immediately with the characters that have already
been received, even if no characters have been received.


So if you have 0 bytes received that is probably perfectly ok for you.
You have following case.
1. Send byte.
2. Try to read what ever is present in read queue. (Please note that your device had no chance even to send one character so you
got zero bytes read);

Change COMMTIMEOUT read parameters.
Or add some sleep between steps 1 and 2.

Regards,
Slobodan


George said:
Slobodan,
ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

Though character data is sent to commport, "dwBytesRead" is always 0 and the
data is not stacked in "byBuffer".
WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);

This works successfully. "dwBytesWritten" is always 9.


George

Slobodan Brcin (eMVP) said:
Hi George,

What happens in this code?
If it get stuck on GetOverlappedResults then it is expected behavior.

You told to read command to wait for 1024 characters and not for 1. And at the same time you are using infinite timeouts so read
will never end. (Well it will if you receive 1024 characters)
ReadFile(nComID, byBuffer, 1024, 0, &read_os);

Switch count to 1. And if this does not work use HyperTerminal to test your connection and let us know if that helped.

Regards,
Slobodan





George said:
Sorry for annoying you by my many misunderstandings.
I'll post the full source code of the sample console program that only send
and receive simple character data.


/////////////////////////////////////////////////////////////Start Of
Source////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "windows.h"

HANDLE hWnd;
HANDLE nComID;
OVERLAPPED read_os;
OVERLAPPED write_os;

BYTE byBuffer[1024];

void Initialize();
long OpenCommPort();
long CloseCommPort();

int main(int argc, char* argv[])
{

char cSel[2];
DWORD dwBytesWritten;
DWORD dwBytesRead;

Initialize();

if(OpenCommPort() == -1){
printf("OpenCommPort Error.\n");
return 1;
}

do{
printf("Select operation. R:Read, W:Write, Q:Quit -> ");
scanf(" %c", &cSel[0]);

if(cSel[0] == 'W' || cSel[0] == 'w' ){
WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);
}

if(cSel[0] == 'R' || cSel[0] == 'r' ){
ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

if(dwBytesRead != 0){
printf("received data = ");
for(unsigned int i=0; i < dwBytesRead ; i++){
putchar(byBuffer);
}
printf("\n");
}else{
printf("No data.\n");
}
Sleep(100);
}

if(cSel[0] == 'Q' || cSel[0] == 'q' ){
break;
}

}while(TRUE);

CloseCommPort();
return 0;
}

/***********************************************************************************************
*******************************************Initialization*****************************************
************************************************************************************************/
void Initialize(){
nComID = INVALID_HANDLE_VALUE;

memset(&write_os, 0, sizeof(OVERLAPPED));
memset(&read_os, 0, sizeof(OVERLAPPED));

read_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name
write_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name

}


/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];
char cPortNum[2];
char cPort[5];

printf("Com Port No? -> ");
scanf(" %c", &cPortNum[0]);

if(cPortNum[0] == '1'){
memcpy(cPort, "COM1", 4);
}else if(cPortNum[0] == '2'){
memcpy(cPort, "COM2", 4);
}else if(cPortNum[0] == '3'){
memcpy(cPort, "COM3", 4);
}else if(cPortNum[0] == '4'){
memcpy(cPort, "COM4", 4);
}else{
return -1;
}

cPort[4] = NULL;

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile(cPort,
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

if(nComID == INVALID_HANDLE_VALUE){
printf("CreateFile Error.\n");
return -1;
}
printf("CreateFile\n");

//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, cPort);
strcat(szPortSet, ":9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);

if(bBuildComm == FALSE){
printf("BuildCommDCB Error.\n");
return -1;
}
printf("BuildCommDCB\n");


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);

if(bSetCommStateRtn == FALSE){
printf("SetCommState Error.\n");
return -1;
}
printf("SetCommState\n");

/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
printf("SetCommTimeouts Error.\n");
return -1;
}
printf("SetCommTimeouts\n");

return 0;
}

/***********************************************************************************************
*******************************************Close
ComPort*****************************************
************************************************************************************************/
long CloseCommPort(){
CloseHandle(nComID);
return 0;

}

/////////////////////////////////////////////////////////////End Of
Source////////////////////////////////////////////////////////////////////////

:

As mentioned in the previous reply post, if 2nd parameter of ReadFile is set
NULL, GetLastError doesn't return ERROR_IO_PENDING.

I do not understand :-(
Second parameter is lpvBuf, right? Why would you like to set it to 0?

I need to see piece of code that you wrote starting from read_os, write_os structure initialization. And that include both readfile
and writefile operations, without any line skipped in between.

I used some free tools that monitor serial port I/O. I could confirm the
output data flow but not input data at all.


Use null cable and second computer to receive text. Then try using WriteFile few times one after another to send some different
data. Look if you will receive in terminal all bytes that you have send. (You will probably have data loss since you did not waited
for transmit to be over, but this is the issue that you have probably not seen yet)

Regards,
Slobodan

 
G

Guest

Slobodan,
Change COMMTIMEOUT read parameters.

I changed the field of COMMTIMEOUT as following.

ReadTotalTimeoutConstant = 1000;
ReadTotalTimeoutMultiplier = 10;

But no change.
Or add some sleep between steps 1 and 2.

The interval between 1 and 2 is enough.


I think commport driver cannot detect the signal by unknown reason though it
is sent.


Slobodan Brcin (eMVP) said:
Hi George,

I have lost you, and what problem you currently have, please read following and give me explanation of what is that you see that is
happening.


Following is from Platform SDK:
COMMTIMEOUTS: ReadIntervalTimeout, A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant and
ReadTotalTimeoutMultiplier members, specifies that the read operation is to return immediately with the characters that have already
been received, even if no characters have been received.


So if you have 0 bytes received that is probably perfectly ok for you.
You have following case.
1. Send byte.
2. Try to read what ever is present in read queue. (Please note that your device had no chance even to send one character so you
got zero bytes read);

Change COMMTIMEOUT read parameters.
Or add some sleep between steps 1 and 2.

Regards,
Slobodan


George said:
Slobodan,
ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

Though character data is sent to commport, "dwBytesRead" is always 0 and the
data is not stacked in "byBuffer".
WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);

This works successfully. "dwBytesWritten" is always 9.


George

Slobodan Brcin (eMVP) said:
Hi George,

What happens in this code?
If it get stuck on GetOverlappedResults then it is expected behavior.

You told to read command to wait for 1024 characters and not for 1. And at the same time you are using infinite timeouts so read
will never end. (Well it will if you receive 1024 characters)
ReadFile(nComID, byBuffer, 1024, 0, &read_os);

Switch count to 1. And if this does not work use HyperTerminal to test your connection and let us know if that helped.

Regards,
Slobodan





Sorry for annoying you by my many misunderstandings.
I'll post the full source code of the sample console program that only send
and receive simple character data.


/////////////////////////////////////////////////////////////Start Of
Source////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "windows.h"

HANDLE hWnd;
HANDLE nComID;
OVERLAPPED read_os;
OVERLAPPED write_os;

BYTE byBuffer[1024];

void Initialize();
long OpenCommPort();
long CloseCommPort();

int main(int argc, char* argv[])
{

char cSel[2];
DWORD dwBytesWritten;
DWORD dwBytesRead;

Initialize();

if(OpenCommPort() == -1){
printf("OpenCommPort Error.\n");
return 1;
}

do{
printf("Select operation. R:Read, W:Write, Q:Quit -> ");
scanf(" %c", &cSel[0]);

if(cSel[0] == 'W' || cSel[0] == 'w' ){
WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);
}

if(cSel[0] == 'R' || cSel[0] == 'r' ){
ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

if(dwBytesRead != 0){
printf("received data = ");
for(unsigned int i=0; i < dwBytesRead ; i++){
putchar(byBuffer);
}
printf("\n");
}else{
printf("No data.\n");
}
Sleep(100);
}

if(cSel[0] == 'Q' || cSel[0] == 'q' ){
break;
}

}while(TRUE);

CloseCommPort();
return 0;
}

/***********************************************************************************************
*******************************************Initialization*****************************************
************************************************************************************************/
void Initialize(){
nComID = INVALID_HANDLE_VALUE;

memset(&write_os, 0, sizeof(OVERLAPPED));
memset(&read_os, 0, sizeof(OVERLAPPED));

read_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name
write_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name

}


/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];
char cPortNum[2];
char cPort[5];

printf("Com Port No? -> ");
scanf(" %c", &cPortNum[0]);

if(cPortNum[0] == '1'){
memcpy(cPort, "COM1", 4);
}else if(cPortNum[0] == '2'){
memcpy(cPort, "COM2", 4);
}else if(cPortNum[0] == '3'){
memcpy(cPort, "COM3", 4);
}else if(cPortNum[0] == '4'){
memcpy(cPort, "COM4", 4);
}else{
return -1;
}

cPort[4] = NULL;

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile(cPort,
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

if(nComID == INVALID_HANDLE_VALUE){
printf("CreateFile Error.\n");
return -1;
}
printf("CreateFile\n");

//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, cPort);
strcat(szPortSet, ":9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);

if(bBuildComm == FALSE){
printf("BuildCommDCB Error.\n");
return -1;
}
printf("BuildCommDCB\n");


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);

if(bSetCommStateRtn == FALSE){
printf("SetCommState Error.\n");
return -1;
}
printf("SetCommState\n");

/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
printf("SetCommTimeouts Error.\n");
return -1;
}
printf("SetCommTimeouts\n");

return 0;
}

/***********************************************************************************************
*******************************************Close
ComPort*****************************************
************************************************************************************************/
long CloseCommPort(){
CloseHandle(nComID);
return 0;

}

/////////////////////////////////////////////////////////////End Of
Source////////////////////////////////////////////////////////////////////////

:

As mentioned in the previous reply post, if 2nd parameter of ReadFile is set
NULL, GetLastError doesn't return ERROR_IO_PENDING.

I do not understand :-(
Second parameter is lpvBuf, right? Why would you like to set it to 0?

I need to see piece of code that you wrote starting from read_os, write_os structure initialization. And that include both
readfile
and writefile operations, without any line skipped in between.

I used some free tools that monitor serial port I/O. I could confirm the
output data flow but not input data at all.


Use null cable and second computer to receive text. Then try using WriteFile few times one after another to send some different
data. Look if you will receive in terminal all bytes that you have send. (You will probably have data loss since you did not
waited
for transmit to be over, but this is the issue that you have probably not seen yet)

Regards,
Slobodan

 
S

Slobodan Brcin \(eMVP\)

Hi George,

Have you tried to use hyper terminal application to test your connection?

Also when you put timeouts is there any difference in regards on how long it take to operation to complete. Use bigger values just
to check this.

Regards,
Slobodan


George said:
Slobodan,
Change COMMTIMEOUT read parameters.

I changed the field of COMMTIMEOUT as following.

ReadTotalTimeoutConstant = 1000;
ReadTotalTimeoutMultiplier = 10;

But no change.
Or add some sleep between steps 1 and 2.

The interval between 1 and 2 is enough.


I think commport driver cannot detect the signal by unknown reason though it
is sent.


Slobodan Brcin (eMVP) said:
Hi George,

I have lost you, and what problem you currently have, please read following and give me explanation of what is that you see that is
happening.


Following is from Platform SDK:
COMMTIMEOUTS: ReadIntervalTimeout, A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant and
ReadTotalTimeoutMultiplier members, specifies that the read operation is to return immediately with the characters that have already
been received, even if no characters have been received.


So if you have 0 bytes received that is probably perfectly ok for you.
You have following case.
1. Send byte.
2. Try to read what ever is present in read queue. (Please note that your device had no chance even to send one character so you
got zero bytes read);

Change COMMTIMEOUT read parameters.
Or add some sleep between steps 1 and 2.

Regards,
Slobodan


George said:
Slobodan,

ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

Though character data is sent to commport, "dwBytesRead" is always 0 and the
data is not stacked in "byBuffer".

WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);

This works successfully. "dwBytesWritten" is always 9.


George

:

Hi George,

What happens in this code?
If it get stuck on GetOverlappedResults then it is expected behavior.

You told to read command to wait for 1024 characters and not for 1. And at the same time you are using infinite timeouts so read
will never end. (Well it will if you receive 1024 characters)
ReadFile(nComID, byBuffer, 1024, 0, &read_os);

Switch count to 1. And if this does not work use HyperTerminal to test your connection and let us know if that helped.

Regards,
Slobodan





Sorry for annoying you by my many misunderstandings.
I'll post the full source code of the sample console program that only send
and receive simple character data.


/////////////////////////////////////////////////////////////Start Of
Source////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "windows.h"

HANDLE hWnd;
HANDLE nComID;
OVERLAPPED read_os;
OVERLAPPED write_os;

BYTE byBuffer[1024];

void Initialize();
long OpenCommPort();
long CloseCommPort();

int main(int argc, char* argv[])
{

char cSel[2];
DWORD dwBytesWritten;
DWORD dwBytesRead;

Initialize();

if(OpenCommPort() == -1){
printf("OpenCommPort Error.\n");
return 1;
}

do{
printf("Select operation. R:Read, W:Write, Q:Quit -> ");
scanf(" %c", &cSel[0]);

if(cSel[0] == 'W' || cSel[0] == 'w' ){
WriteFile(nComID, "COMMTEST", 9, 0, &write_os);
GetOverlappedResult(nComID, &write_os, &dwBytesWritten, TRUE);
}

if(cSel[0] == 'R' || cSel[0] == 'r' ){
ReadFile(nComID, byBuffer, 1024, 0, &read_os);
GetOverlappedResult(nComID, &read_os, &dwBytesRead, TRUE);

if(dwBytesRead != 0){
printf("received data = ");
for(unsigned int i=0; i < dwBytesRead ; i++){
putchar(byBuffer);
}
printf("\n");
}else{
printf("No data.\n");
}
Sleep(100);
}

if(cSel[0] == 'Q' || cSel[0] == 'q' ){
break;
}

}while(TRUE);

CloseCommPort();
return 0;
}

/***********************************************************************************************
*******************************************Initialization*****************************************
************************************************************************************************/
void Initialize(){
nComID = INVALID_HANDLE_VALUE;

memset(&write_os, 0, sizeof(OVERLAPPED));
memset(&read_os, 0, sizeof(OVERLAPPED));

read_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name
write_os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL) ; // no name

}


/***********************************************************************************************
*******************************************Open
ComPort*****************************************
************************************************************************************************/
long OpenCommPort(){
DCB dcb;
COMSTAT ComStat;
BOOL bBuildComm;
BOOL bSetCommStateRtn;
char szPortSet[256];
char cPortNum[2];
char cPort[5];

printf("Com Port No? -> ");
scanf(" %c", &cPortNum[0]);

if(cPortNum[0] == '1'){
memcpy(cPort, "COM1", 4);
}else if(cPortNum[0] == '2'){
memcpy(cPort, "COM2", 4);
}else if(cPortNum[0] == '3'){
memcpy(cPort, "COM3", 4);
}else if(cPortNum[0] == '4'){
memcpy(cPort, "COM4", 4);
}else{
return -1;
}

cPort[4] = NULL;

//////////////////////// CreateFile
/////////////////////////////////////////////////

nComID = CreateFile(cPort,
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);

if(nComID == INVALID_HANDLE_VALUE){
printf("CreateFile Error.\n");
return -1;
}
printf("CreateFile\n");

//////////////////////// BuildComm
/////////////////////////////////////////////////

dcb.DCBlength = sizeof(DCB);
GetCommState(nComID, &dcb);
strcpy(szPortSet, cPort);
strcat(szPortSet, ":9600,e,7,2");

bBuildComm = BuildCommDCB(szPortSet,&dcb);

if(bBuildComm == FALSE){
printf("BuildCommDCB Error.\n");
return -1;
}
printf("BuildCommDCB\n");


/////////////////////// SetCommState
/////////////////////////////////////////////

ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
dcb.wReserved = 0;

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = 2;
dcb.ByteSize = 7;
dcb.StopBits = 2;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
//XON/XOFF
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.fTXContinueOnXoff = TRUE;
dcb.XonLim = 2048;
dcb.XoffLim = 2048;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;

dcb.fBinary = TRUE;
dcb.fNull = FALSE;
dcb.fAbortOnError = TRUE;
dcb.fErrorChar = FALSE;
dcb.ErrorChar = 0x00;

bSetCommStateRtn = SetCommState(nComID, &dcb);

if(bSetCommStateRtn == FALSE){
printf("SetCommState Error.\n");
return -1;
}
printf("SetCommState\n");

/////////////////////////////////////////////////////////////////////////////////////////////

if (PurgeComm(nComID, PURGE_TXCLEAR | PURGE_RXCLEAR) != TRUE) {
if (GetLastError() != CE_MODE) {
DWORD dwErrors;
if (ClearCommError(nComID, &dwErrors, &ComStat) != TRUE) {
return GetLastError();
}
}
}

COMMTIMEOUTS comm_timeout;
comm_timeout.ReadIntervalTimeout = MAXDWORD;
comm_timeout.ReadTotalTimeoutMultiplier = 0;
comm_timeout.ReadTotalTimeoutConstant = 0;
comm_timeout.WriteTotalTimeoutMultiplier = 0;
comm_timeout.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(nComID, &comm_timeout)) {
printf("SetCommTimeouts Error.\n");
return -1;
}
printf("SetCommTimeouts\n");

return 0;
}

/***********************************************************************************************
*******************************************Close
ComPort*****************************************
************************************************************************************************/
long CloseCommPort(){
CloseHandle(nComID);
return 0;

}

/////////////////////////////////////////////////////////////End Of
Source////////////////////////////////////////////////////////////////////////

:

As mentioned in the previous reply post, if 2nd parameter of ReadFile is set
NULL, GetLastError doesn't return ERROR_IO_PENDING.

I do not understand :-(
Second parameter is lpvBuf, right? Why would you like to set it to 0?

I need to see piece of code that you wrote starting from read_os, write_os structure initialization. And that include both
readfile
and writefile operations, without any line skipped in between.

I used some free tools that monitor serial port I/O. I could confirm the
output data flow but not input data at all.


Use null cable and second computer to receive text. Then try using WriteFile few times one after another to send some different
data. Look if you will receive in terminal all bytes that you have send. (You will probably have data loss since you did not
waited
for transmit to be over, but this is the issue that you have probably not seen yet)

Regards,
Slobodan

 
G

Guest

Thread tree became deeper beyond visible area for my monitor.

Well, my application was working on Windows NT correctly.
Why doesn't it work on Windows XP?
I can't think my application has any default so far that Windows XP has
upper compatibility with Windows NT regarding serial communication.

The only thing that I can guess is that Windows XP gets severer than NT of
checking of the signal line.
Or some settings that is lacking was ignored or set default value on Windows
NT, but XP treats it as setting error.
 
G

Guest

Here is additional information.
When I check the field "fParity" of DCB structure by GetCommState() API
after setting it "TRUE" by SetCommState() API, it was turned into "FALSE".
Only this field was changed against my setting. Why?
As I set the invalid value for the commport?
But actually SetCommState() API returned "TRUE".


George
 
S

Slobodan Brcin \(eMVP\)

Hi George,

You are wasting days on this simple task. Why don't you use simple 3 wire RS-232 cable between two computers?
Run hyper terminal on both of them and test connection parameters that you want.

Then make init com in your application to wait infinitely for read of one character. Then send this char from terminal.
Only what I can say is simplify your test case. Even remove overlapped access if it will make you feel better.

RS232 it is fairly simple to use, and I have no idea where you got stuck :-(

Regards,
Slobodan
 
G

Guest

Slobodan,

Yes, it's very simple thing so far it is a communication between 2 PCs.
But for embedded system it isn't because it provides many specific devices
and they are connected each other with complecated circuit.

The only event I could catch by WaitCommEvent() was EV_TXEMPTY and EV_CTS.
When WriteFile operation complete, EV_TXEMPTY was sent to my application and
WaitCommEvent() correctly terminated.
When plug or unplug the cable, EV_CTS was sent to my application and
WaitCommEvent() correctly terminated.
But when the device send out a character data, my application can't catch
EV_RXCHAR.

Isn't it possible to simulate 3 wire cable with 9 wire cable?
It is not easy for me to make a special cable.

Sorry for wasting your time.

George
 
S

Slobodan Brcin \(eMVP\)

Hi George,
Isn't it possible to simulate 3 wire cable with 9 wire cable?
It is not easy for me to make a special cable.

Of course. Just disable all hardware flow control and you will be ok.

Like I said many times before try using some windows applications that work for certain. And if you know that they are working you
have problem in your source if not problem is somewhere else.

Unfortunately serial communication is the very low level thing so problem with missing dependencies in XPe do not apply to you :-(

HTH,
Slobodan
 
G

Guest

Slobodan,
Like I said many times before try using some windows applications that work for certain. And if you know that they are working you
have problem in your source if not problem is somewhere else.

I tried some communication software including hyper termianl, but all of
them works just the same as my application.
Sending data goes well but no data is receivable.

Unfortunately serial communication is the very low level thing so problem with missing dependencies in XPe do not apply to you :-(

I'm now testing with XP Pro not XPe and the same phenomenon is occurring
both of them. So my problem shouldn't depend on XPe configuration.


WaitCommEvent doesn't return any input event except EV_CTS. What will this
mean. If an error is happening in the line or data receiving process. I think
it should return EV_ERR. This result indicates that there exists something
fundamental fault.


George
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top