質問

I'm using serial com port communication synchronously with WinApi. And I want to split messages with 13 (CR). How can I use ReadFile function so that it returns when it reads a 13 ?


The DCB struct has a field called EofChar but the function continues to read until it has filled the buffer. If I send only 3 bytes with a 13 it continues to wait for the 2 other bytes. Is it actually possible to make ReadFile read less bytes than the buffer provides and specified by nNumberOfBytesToRead?

  • Incoming dec bytes: 12 12 13 15 18 19 ...
  • Wanted dec bytes: 12 12 13 (but unknown length)


Code:

// 2. reading:
DWORD bytesRead;
char* buffer = new char[5];
ReadFile(handle, buffer, 5, &bytesRead, NULL);
// bytesRead should be 3 in the example above

// 1. connecting:
HANDLE handle = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
DCB dcb;
COMSTAT stat;
if (GetCommState(handle, &dcb))
{
    dcb.BaudRate          = 57600;      // baud rate
    dcb.ByteSize          = 7;          // number of bits/byte, 4-8 
    dcb.Parity            = EVENPARITY; // 0-4=no,odd,even,mark,space 
    dcb.StopBits          = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2  V2.12 0 -> ONESTOPBIT
    dcb.fBinary           = TRUE;       // binary mode, no EOF check 
    dcb.fParity           = TRUE;       // enable parity checking 
    dcb.fOutxCtsFlow      = FALSE;      // CTS output flow control 
    dcb.fOutxDsrFlow      = FALSE;      // DSR output flow control 
    dcb.fDtrControl       = 0;          //DTR_CONTROL_DISABLE; // DTR flow control type
    dcb.fRtsControl       = 0;          //RTS_CONTROL_DISABLE; // RTS flow control 
    dcb.fDsrSensitivity   = FALSE;      // DSR sensitivity 
    dcb.fTXContinueOnXoff = FALSE;      // XOFF continues Tx 
    dcb.fOutX             = FALSE;      // XON/XOFF out flow control 
    dcb.fInX              = FALSE;      // XON/XOFF in flow control 
    dcb.fErrorChar        = FALSE;      // enable error replacement V2.12 TRUE -> FALSE
    dcb.fAbortOnError     = TRUE;       // abort reads/writes on error 
    dcb.XonChar           = 0x00;       // Tx and Rx XON character 0x01
    dcb.XoffChar          = 0x00;       // Tx and Rx XOFF character 0x02
    dcb.ErrorChar         = 0x1f;       // error replacement character  
    dcb.EofChar           = 0x0d;       // end of input character 0x00
    dcb.EvtChar           = 0x00;       // received event character 0x0d

    if (SetCommState(handle, &dcb))
    {
        EscapeCommFunction(handle, SETRTS);
        EscapeCommFunction(handle, SETDTR);
        EscapeCommFunction(handle, CLRRTS);
        EscapeCommFunction(handle, CLRDTR);
        PurgeComm(handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
        return true;
    }
}
役に立ちましたか?

解決

No, that's very unlikely to work. Windows itself doesn't do anything with the DCB.EofChar you specify. Or for that matter any of the other special characters in the DCB. It directly passes it to the device driver, the underlying ioctl is IOCTL_SERIAL_SET_CHARS. Leaving it entirely up to the driver to implement them.

Most hardware vendors that write serial port drivers (USB emulators most of all these days), use the sample driver code that's included in the WDK. Which does nothing with SERIAL_CHARS.EofChar. So the inevitable outcome is that nobody implements it. I personally have never encountered one, knowingly anyway.

So it is expected not to have any effect.

You can usually expect DCB.EvtChar to work, it powers the EV_RXFLAG option for WaitCommEvent(). In other words, if you set it to the line terminator then it can give you a signal that ReadFile() is going to return at least a complete line.

But you explicitly said you don't want to do this. Everybody solves this by simply buffering the extra data that is returned by ReadFile(). Or by reading one byte at a time, which is okay because serial ports are slow anyway.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top