【发布时间】:2016-02-29 08:11:39
【问题描述】:
我编写了一个小型 C 程序,用于监控串行端口流量(信号和输入)。我使用的应用程序是一个同步的、事件驱动的应用程序。我同步调用WaitCommEvent 函数(所以不使用 使用OVERLAPPED 结构)。
在我的应用程序中监视以下 COM 事件:
-
EV_CTS:CTS(清除发送)信号状态改变 -
EV_RLSD: RLSD (receive-line-signal-detect) 信号状态改变 -
EV_RXCHAR: 接收到一个字符并将其放入输入缓冲区中
我的问题是,如果上面提到的信号之一改变了它的状态,那么WaitCommEvent(第二个参数)的输出掩码具有它的值(EV_CTS(0x0008)或EV_RLSD (0x0020),如果信号被设置)或EV_RXCHAR 的值(0x0001,如果信号被清除)。换句话说:如果其中一个信号被清除,那么对于“清除事件”,我会收到一个EV_RXCHAR,所以我的软件无法区分“收到字符”和“信号清除”事件。
请帮我找到一个想法,让我的软件能够区分“收到字符”和“清除信号”事件。 WinApi 为这两种情况返回事件掩码值0x0001。
更新:
为了更好地理解我的问题,我发布了我的程序的代码和控制台输出。
串行总线上发生以下情况(我的应用程序也应该检测到):
- RLSD 信号已设置。
- 数据已发送(因此应由我的应用程序读取/接收)。
- RLSD 信号被清除。
事件处理的代码如下:
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);
}
}
我在控制台上得到的输出如下:
2015.11.26 11:51:03:578 dwEvtMask = 0x0020
2015.11.26 11:51:03:593 dwModemState = 0x0080
2015.11.26 11:51:03:593 EV_RLSD 触发。
2015.11.26 11:51:03:656 dwEvtMask = 0x0020
2015.11.26 11:51:03:656 dwModemState = 0x0000
2015.11.26 11:51:03:656 EV_RLSD 触发。
2015.11.26 11:51:03:671 dwEvtMask = 0x0001
2015.11.26 11:51:03:671 dwModemState = 0x0000
2015.11.26 11:51:03:671 在端口 COM1 上收到 3 个字符:07 01 06
2015.11.26 11:51:03:671 dwEvtMask = 0x0001
2015.11.26 11:51:03:671 dwModemState = 0x0000
2015.11.26 11:51:03:671 在端口 COM1 上收到 0 个字符:
也许 WinApi 不像 MSDN 里写的那样,谁知道呢……
更新 2:
正如 Hans Passant 在下面所写,问题是,我总是在 EV_RLSD 之后收到事件 EV_RXCHAR,这导致了误解。我必须使用的协议定义了,数据只应在设置 RLSD 信号期间接收。确实如此,所以总线动作正确,但是由于接收需要一些时间(因为序列化等原因,详情见上面Hans Passant的帖子)。
如果 RLSD 信号“下降”(1 -> 0),我可以通过检查 EV_RLSD 上是否接收到数据(通过调用 ReadFile)来解决问题。
【问题讨论】:
-
听起来你做对了,但是你能显示一些代码吗?
-
根据
WaitCommEvent的文档,EV_CTS/EV_RLSD 位将在信号更改时设置,这意味着更改 0->1 或更改 1->0。您可能需要拨打GetCommModemStatus来获取CTS/RLSD 的值。接收 EV_RXCHAR 并不意味着清除 CLS/RLSD。您可能需要检查您的代码,否则该函数的行为与文档不符。 -
仔细阅读,尤其是接收多个字符时有关 EV_RXCHAR 的部分。 msdn.microsoft.com/en-us/library/ff802693.aspx
-
亲爱的 Roddy,我使用同步
WaitCommEvent(这意味着不存在 OVERLAPPED 结构)。因此,样本对我没有帮助。我使用的应用程序是单线程应用程序,因为实时性是它的关键。 -
尊敬的 user1969104,我阅读的 MSDN 源代码可以在这里找到:msdn.microsoft.com/en-us/library/windows/desktop/… 但我发布了我的软件的代码和输出。
标签: c windows winapi serial-port