3

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 state
  • EV_RLSD: the RLSD (receive-line-signal-detect) signal changed state
  • EV_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):

  1. The RLSD signal is set.
  2. Data is sent (so should be read/received by my application).
  3. 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).

7
  • It sounds like you're doing things right, but can you show some code, please? Commented Nov 26, 2015 at 10:04
  • As per the documentation of 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 call GetCommModemStatus to 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. Commented Nov 26, 2015 at 10:06
  • Read this carefully, particularly the bit about EV_RXCHAR when multiple characters are received. msdn.microsoft.com/en-us/library/ff802693.aspx Commented Nov 26, 2015 at 10:14
  • Dear Roddy, I use the synchronous 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. Commented Nov 26, 2015 at 10:25
  • Dear user1969104, The MSDN source I read can be found here: msdn.microsoft.com/en-us/library/windows/desktop/… But I post the code and the output of my software. Commented Nov 26, 2015 at 10:25

1 Answer 1

2

distinguish between "character received" and "signal cleared" events

That's not what EV_CTS and EV_RLSD mean, they only indicate that the signal changed state, they don't say that it is "cleared". It is up to you to use the event to then call GetCommModemStatus() and obtain the actual signal state. So getting 0x0001 only means that a byte was received, the signal did not change.

The event mask helps you to minimize the number of function calls you need to make. So calling GetCommModemStatus() for every single event is not necessary. Do beware that you might get multiple events signaled at the same time.

There is another hint of a problem visible in the way you ordered the events you expected to get. You hope to get EV_RLSD after EV_RXCHAR. Not the way it works, the handshake signal changes are effective immediately. But transmitting and receiving a byte takes time. The byte has to be serialized by the UART on the device, typically takes 10 times the baudrate clock. The UART on the PC puts the byte in a FIFO buffer which eventually generates an interrupt to tell the driver to copy the byte into its receive buffer. Then you get the EV_RXCHAR event.

So using DCD as some kind of "gate" signal is not useful. The device cannot possibly know when the PC receives the byte, it will always turn off DCD too early. Lots of games you can play with the handshake signals, they however usually don't turn out that well. DCD is a modem signal that is only used to negotiate the connection, using it for something else begets a baroque kind of protocol that few programmers know how to implement correctly.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.