DCB 结构的 fParity 成员在 GetCommState 之后始终为 FALSE

fParity member of DCB structure always FALSE after a GetCommState

含着血泪,我才发现每次调用 GetCommState 时,DCB 结构的 fParity 成员都被主动设置为 FALSE。

是否有解决方法(除了显式设置 dcb.fParity = 1;每次您需要调用 SetCommState)?有没有人遇到过这个问题?是否有 MSDN 文章解释此行为?

这是在我的 PC 上重现问题的 MCVE:

int main()
{
  HANDLE hComm;
  DCB dcb;

  // Replace COM1 by any COM port identifier on your PC
  hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
  if (hComm == INVALID_HANDLE_VALUE)
  {
    printf("Failed COM opening. Exit.");
    return -1;
  }

  FillMemory(&dcb, sizeof(dcb), 0);
  dcb.DCBlength = sizeof(dcb);

  // Get the current DCB structure
  if (!GetCommState(hComm, &dcb))
  {
    printf("Failed GetCommState. Exit.");
    return -1;
  }

  // [Here, you may set any or all members of the dcb structure]
  // As suggested by chux and Hans Passant in a comment, try to set the parity to make the fParity value relevant.
  dcb.Parity = MARKPARITY;


  // This is the relevant bit :
  dcb.fParity = TRUE;

  // Set the new COM state.
  if (!SetCommState(hComm, &dcb))
  {
    printf("Failed SetCommState. Exit.");
    return -1;
  }

  // Read back the COM state (fParity should be TRUE)
  if (!GetCommState(hComm, &dcb))
  {
    printf("Failed GetCommState. Exit.");
    return -1;
  }

  printf("fParity = %d\n", dcb.fParity); // fParity value is 0.

  CloseHandle(hComm);
}

在 GetCommState() 之后唯一没有正确读回的值是 fParity。

我就此事联系了微软,半官方的回答是,是的,的确,DCB 结构的 fParity 成员存在错误,因为该值没有被 GetCommState()fParity 的值将始终为 false(即使文档说默认值为 true)。

他们还告诉我驱动程序根本不检查 fParity 标志,并且根据 Parity 标志设置报告(或不报告)奇偶校验错误。

最后一点信息让我有点难过,因为关于 DCB 的 MSDN 页面明确指出结构的另一个成员 fErrorChar 不会生效,除非 fParity 为真.关于 fErrorChar.

的行为,我从未得到令人满意的解释

我怀疑 MSDN 文档对 COM 驱动程序的功能有误导,这让 Microsoft 很尴尬。无论如何,除非大量遗留应用程序突然面临向后兼容性问题,否则无法解决此问题。

从上面的代码看来,您正在使用标记和 space 奇偶校验方案进行通信。当您调用 GetCommState 时,您在 Parity 字段中得到了什么。

因为 GetCommState 没有返回 fParity 作为 True,它可能有助于调用 ClearCommError 并检查第二个输出参数 COMSTAT 是否有 CE_RXPARITY.不确定你的情况是否有效,但在端口上收到一些数据后调用 ClearCommError 时,它应该有效。