3

我正在编写一个应用程序,它使用 OpenNETCF.IO.Serial(开源,请参阅此处的串行代码)在 Windows CE 6.0 设备上进行串行通信。此应用程序在 Compact Framework 2.0 中使用 C# 编码。我不相信我将要描述的问题与这些细节特别相关,但在这方面我可能被证明是错误的。

我遇到的问题是,看似随机(读作:间歇性问题,我还不能可靠地复制),数据将无法传输或接收,直到设备本身重新启动。Windows CE 设备与运行完全不同的应用程序的系统通信。重新启动此其他系统并断开/重新连接通信电缆似乎无法解决此问题,只能重新启动 Windows CE 设备。

发生此问题的唯一迹象是缺少来自 OpenNETCF 触发的 TxDone 事件(在 OpenNETCF.IO.Serial 类中查找“TxDone();”),并且当我知道已连接的事实时没有接收到数据系统正在发送数据。

可以在我们的串行通信中发送和接收 1 - 255 (0x01 - 0xFF) 的任何字符值。空值被丢弃。

我的串行设置是 38400 波特、8 个数据位、无奇偶校验、1 个停止位(38400、8n1)。我已将输入和输出缓冲区大小设置为 256 字节。每当我们接收到 1 个或更多字符时发生 DataReceived 事件,并且当输出缓冲区中有 1 个或更多字节时发生传输,因为消息的长度是可变的。

不使用握手。由于这是 RS422,因此只使用了 4 个信号:RX+、RX-、TX+、TX-。

我收到一个“DataReceived”事件,我从输入缓冲区读取所有数据,并在我的代码中创建自己的缓冲区,以便在 DataReceived 事件之外空闲时解析它。当我收到一条命令消息时,我会发回一条快速确认消息。当其他系统收到来自 Windows CE 设备的命令消息时,它会返回一个快速确认消息。确认消息不会得到进一步的回复,因为它们的目的是简单的“是的,知道了”。在我的代码中,我通过多个线程接收/传输,所以我使用 lock 关键字,所以我不会在多个线程上同时传输多条消息。仔细检查代码表明我没有挂断任何锁。

在这一点上,我想知道我是否一直遗漏一些关于串行通信如何工作的明显内容,例如我是否需要设置一些变量或属性,而不是在输入缓冲区不为空时读取并写入传输缓冲区。

欢迎任何见解、检查选项、建议、想法等。这是我几个月来一直在努力解决的问题,我希望我在这里收到的答案或评论可以帮助解决这个问题。先感谢您。

编辑,2011 年 2 月 24 日:
(1) 我似乎只能在 Windows CE 设备正在与之通信的系统启动时重新创建错误,而不是每次启动。我还查看了信号,共模电压波动,但系统启动时出现的噪声幅度似乎与问题是否发生无关,我已经看到 25V 峰峰值没有问题,当 5V 峰值-to-peak 问题再次发生)。
问题听起来越来越与硬件相关,但我试图找出可能导致我看到的症状的原因,因为实际上没有任何硬件出现故障或关闭,至少在我能够达到的地方测量信号。很抱歉,但我无法提供任何类型的硬件零件编号,所以请不要询问正在使用的组件。

(2) 根据@ctacke 的建议,为了可维护性,我确保所有传输都经过同一个位置,我放入的线程安全基本上如下:

lock(transmitLockObj)
{
    try
    {
        comPort.Output = data;
    }
    [various catches and error handling for each]
}

(3) 出现 UART OVERRUN 错误,在测试中,以 38400 波特的大约 300 毫秒时间间隔发送和接收 <10 个字节。一旦它得到一个错误,它就进入下一个循环迭代,并且不运行 ReadFile,并且不运行 TxDone 事件(或任何其他行检查过程)。此外,关闭和重新打开端口不仅无法解决此问题,而且在设备仍在运行时重新启动软件也无济于事。只有硬件重启。

我的 DataReceived 事件如下:

try
{
    byte[] input = comPort.Input; //set so Input gets FULL RX buffer

    lock(bufferLockObj)
    {
        for (int i = 0; i < input.Length; i++)
        {
            _rxRawBuffer.Enqueue(input[i]);
            //timer regularly checks this buffer and parses data elsewhere
            //there, it is "lock(bufferLockObj){dataByte = _rxRawBuffer.Dequeue();}"
            //so wait is kept short in DataReceived, while remaining safe
        }
    }
}
catch (Exception exc)
{
    //[exception logging and handling]
    //hasn't gotten here, so no point in showing
}

然而,在测试中第一次 WriteFile 调用超时后,我开始收到 UART OVERRUN 错误。老实说,我看不到导致 UART OVERRUN 条件的代码。

想法?硬件或软件相关,我正在检查所有我能想到的检查。

4

2 回答 2

1

一切听起来都是对的,但你的观察表明它们不是。

由于您已经声明您从多个线程发送,所以我要做的第一件事是放入某种发送机制,在调用串行对象实例之前,所有发送请求都进入一个位置。当然,您说您确保了线程安全,但是通过一个位置序列化这些调用将有助于加强这一点(并使代码更易于维护/可扩展)。

接下来,我可能会在 Serial lib 中添加一些临时处理,以便在您完成 Tx 但 TxDone 事件在某个边界时间内没有触发时专门设置一个事件或在调试器中中断。串行库中总是有可能存在错误(相信我,该代码的作者远非万无一失),其中一些竞争条件正在过去。

于 2011-02-10T15:37:41.830 回答
0

感谢所有回复的人。我们发现这实际上似乎与硬件有关。恐怕我不能提供比这更多的信息,但我感谢所有提供可能的解决方案或故障排除步骤的人。

于 2011-04-19T14:26:38.717 回答