I wrote a small C program, that monitors the serial ports traffic (signals and input). The application I use, is an synchron, event-driven application. I call WaitCommEvent function synchronously (so without using OVERLAPPED structure).
The following COM events are monitored in my application:
EV_CTS: the CTS (clear-to-send) signal changed stateEV_RLSD: the RLSD (receive-line-signal-detect) signal changed stateEV_RXCHAR: a character was received and placed in the input buffer
My problem is, that if one of the signals mentioned above changed its state, then the output mask of WaitCommEvent (2nd parameter) has either the value of it (EV_CTS (0x0008) or EV_RLSD (0x0020) if the signal is set) or the value of EV_RXCHAR (0x0001 if the signal is cleared). With other words: if one of those signals are cleared, than for the "clear event" I receive an EV_RXCHAR, so my software cannot distingish between "character received" and "signal cleared" event.
Please help me find an idea for my software to be able to distinguish between "character received" and "signal cleared" events. The WinApi returns for both cases the events mask value 0x0001.
UPDATE:
To better understand my problem, I post the code and the console output of my program.
The following happens on the serial bus (what my application should also detect):
- The RLSD signal is set.
- Data is sent (so should be read/received by my application).
- The RLSD signal is cleared.
The code for event handling is the following:
if(TRUE == WaitCommEvent(hComPort, &dwEvtMask, NULL))
{
PrintCurrentDateTime();
printf("the dwEvtMask = 0x%04X\r\n", dwEvtMask);
GetCommModemStatus(hComPort, &dwModemState);
PrintCurrentDateTime();
printf("the dwModemState = 0x%04X\r\n", dwModemState);
if(dwEvtMask & EV_CTS) // Clear-to-send signal changed
{
PrintCurrentDateTime();
printf("EV_CTS triggered.\r\n");
}
if(dwEvtMask & EV_RLSD) // Data-carrier-detect signal changed
{
PrintCurrentDateTime();
printf("EV_RLSD triggered.\r\n");
}
if(dwEvtMask & EV_RXCHAR) // Data received
{
ReadSerial(hComPort, portNum, readBuff, READ_BUFF_MAX_LENGTH);
}
}
The output I get on the console is the following:
2015.11.26 11:51:03:578 the dwEvtMask = 0x0020
2015.11.26 11:51:03:593 the dwModemState = 0x0080
2015.11.26 11:51:03:593 EV_RLSD triggered.
2015.11.26 11:51:03:656 the dwEvtMask = 0x0020
2015.11.26 11:51:03:656 the dwModemState = 0x0000
2015.11.26 11:51:03:656 EV_RLSD triggered.
2015.11.26 11:51:03:671 the dwEvtMask = 0x0001
2015.11.26 11:51:03:671 the dwModemState = 0x0000
2015.11.26 11:51:03:671 Received 3 characters on port COM1: 07 01 06
2015.11.26 11:51:03:671 the dwEvtMask = 0x0001
2015.11.26 11:51:03:671 the dwModemState = 0x0000
2015.11.26 11:51:03:671 Received 0 characters on port COM1:
Maybe the WinApi does not act like is written in the MSDN, who knows...
UPDATE2:
As written below by Hans Passant, the problem is, that I receive the event EV_RXCHAR always after the EV_RLSD, that led to the misunderstanding. The protocol I have to use defines, that data should only be received during the RLSD signal is set. It is the case, so the bus acts correctly, but since the receive takes some time (because of serialization etc., for details see Hans Passant's post above).
I could solve the problem by checking wheter data received (by calling ReadFile) on EV_RLSD if the RLSD signal "goes down" (1 -> 0).
WaitCommEvent, EV_CTS/EV_RLSD bit will be set when the signal changes, which would mean either the change 0->1 or the change 1->0. You may nee to callGetCommModemStatusto get the value of CTS/RLSD. Receiving EV_RXCHAR does not mean clearing of CLS/RLSD. You may need to check you code or the function is not behaving as per the documentation.WaitCommEvent(it means, that the OVERLAPPED structure is not present). Therefore the sample does not help me. The application I use is a single-threaded application, since real-time is a key for it.