【问题标题】:ReadFile + Eof CharReadFile + Eof 字符
【发布时间】:2014-05-29 17:40:34
【问题描述】:

我正在使用串行 com 端口通信 同步 与 WinApi。我想用 13 (CR) 拆分消息。如何使用 ReadFile function 以便在读取 13 时返回?


DCB 结构有一个名为EofChar 的字段,但该函数会继续读取,直到它填满缓冲区。如果我只用 13 发送 3 个字节,它会继续等待另外 2 个字节。实际上是否有可能使 ReadFile 读取的字节数少于缓冲区提供并由nNumberOfBytesToRead 指定?
  • 传入的十进制字节:12 12 13 15 18 19 ...
  • 需要的十进制字节:12 12 13(但长度未知)


代码:
// 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;
    }
}

【问题讨论】:

  • 你不能。您必须在他们到来时阅读再见并自己应对 CR。

标签: c++ winapi serial-port


【解决方案1】:

不,这不太可能奏效。 Windows 本身不会对您指定的 DCB.EofChar 做任何事情。或者就此而言,DCB 中的任何其他特殊字符。它直接将它传递给设备驱动程序,底层的ioctl是IOCTL_SERIAL_SET_CHARS。完全由驱动程序来实现它们。

大多数编写串行端口驱动程序的硬件供应商(这些天大多是 USB 模拟器)都使用 WDK 中包含的示例驱动程序代码。 SERIAL_CHARS.EofChar 什么都没有。所以不可避免的结果是没有人实施它。无论如何,我个人从未遇到过。

所以预计不会有任何影响。

您通常可以期望 DCB.EvtChar 工作,它为 WaitCommEvent() 的 EV_RXFLAG 选项提供动力。换句话说,如果你将它设置为行终止符,那么它可以给你一个信号,表明 ReadFile() 将返回至少一个完整的行。

但您明确表示您不想这样做。每个人都通过简单地缓冲 ReadFile() 返回的额外数据来解决这个问题。或者一次读取一个字节,这没关系,因为串行端口无论如何都很慢。

【讨论】:

  • 我当前的“解决方案”一次只处理一个字节。我希望避免这种情况,因为 理论上不必要 CPU 使用率。 ...哦,好吧。
  • 然后你必须使用更大的缓冲区读取端口并将任何读取的数据缓存到一边,每次都扫描该缓存以查找新的 CR。
  • @RemyLebeau 在我的情况下,传入的数据是响应(如服务器端响应)。长度未知,但它们以0x0d 结尾。 com 服务器 在我什么都不问的时候是静默的。所以每次回复消息结束时,我的缓冲区都不会被完全填满。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 2011-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多