从串口

时间:2018-02-06 08:35:53

标签: c# .net winapi serial-port

我们的C#应用​​程序通过串口与设备通信。该协议是一种简单的请求/响应,如协议。

在大多数情况下,一切都运行正常,但在某些机器上,我们有时会遇到以下请求响应的超时和陈旧数据。

我编写了一个单线程控制台应用程序,并设法在虚拟机中可靠地重现问题,我将CPU限制在10%左右。该应用程序基本上执行以下操作:

_port = new SerialPort(
    "COM1",
    115200,
    Parity.None,
    8,
    StopBits.One)
{
    RtsEnable = false,
    DtrEnable = false,
    Handshake = Handshake.None,
    ReadTimeout = 5000
    WriteTimeout = 5000
};

_port.Open();
_port.DiscardInBuffer();
_port.DiscardOutBuffer();


_readBuffer = new byte[1024];

// Send requests periodically...
while (true)
{
    var requestBytes = ...;                 // Encode the request
    _port.Write(requestBytes, 0, requestBytes.Length);

    try
    {
        var responseStream = new List<byte>(1024);
        int count = ...;                        // Calculate number of bytes of the response
        int remainingBytesCount = count;
        while (numberOfBytesReadTotal < count)
        {
            int bytesToRead = Math.Min(_readBuffer.Length, remainingBytesCount);
            int numberOfBytesRead = _port.Read(_readBuffer, 0, bytesToRead);
            if (numberOfBytesRead <= 0)
                break;

            remainingBytesCount -= numberOfBytesRead;

            responseStream.AddRange(_readBuffer.Take(numberOfBytesRead));
        }

        // Parse the response and if it is valid, dump it. Otherwise throw an exception
        var response = ParseResponse(responseStream);
        Console.WriteLine(FormatResponse(response));
    }
    catch (Exception err)
    {
        Console.WriteLine("ERROR OCCURED: " + err);
        Console.WriteLine("Sleep some time, then discard in and out buffers and then proceed");
        Thread.Sleep(10000);
        _port.DiscardInBuffer();
        _port.DiscardOutBuffer();
    }
}

在短时间内它成功运行,但是在读取响应的过程中突然间,读取循环内的Read()调用超时并抛出TimeoutException

如您所见,应用程序等待10秒钟以确保设备已发送剩余数据。然后我们丢弃串口的输入和输出缓冲区并重新开始。

现在有一个我不理解的非常奇怪的效果:对于下一个请求,读取的数据是尚未从先前请求超时读取的陈旧数据!在我看来,这不应该发生,因为我放弃了进出缓冲区。

为了确保问题不是设备本身,我们的工程师之一将数字示波器放在设备前面并记录数据流量:设备快速响应请求并在一秒钟内将所有响应数据发送到电脑所以应该没有超时。第二,它不会发送错误的数据作为对超时请求之后的请求的响应。

这个问题似乎与CPU的速度有关。当我以全速运行虚拟机时,测试应用程序成功运行几分钟,直到我停止它。我越低CPU速度,越快出现错误。

设备行为正常,小型控制台应用程序似乎是正确的。看起来串口驱动程序有问题。

有没有人可以尝试一些提示?

修改

  • 我发现了一个错误:波特率必须是115200波特而不是115000.但这并没有帮助。
  • 正如评论中所建议的那样,我已经阅读了博文并尝试直接从BaseStream中读取,但这不起作用。
  • 然后我完全扔掉了C#的SerialPort并使用了WinAPI,这也没用。
  • 真正奇怪的是:当超时发生并关闭并重新启动测试应用程序时,会收到上次运行的先前请求的陈旧数据!在我看来,这是不可能的。我还做了一个ClearCommError来查看串口驱动程序的读队列中是否有东西,它是空的。为了安全起见,我在打开端口之后和发送请求之前做了一个PurgeComm,但问题仍然存在。

0 个答案:

没有答案