【问题标题】:Serial Port Performance串口性能
【发布时间】:2014-10-21 04:03:25
【问题描述】:

我想使用 RS232 与 DSP 通信,所以我使用 System.IO.SerialPort 来实现这一点。一切都很顺利,除了阅读表现。

每200ms,端口可以接收一个144字节的包。但在测试中,应用程序几乎跳过所有其他包。我尝试在控制台中打印系统时间。令我惊讶的是,下面的代码(当长度 = 140 时)花了我超过 200 毫秒。它让应用程序无法及时处理数据。

我做错了什么吗?

端口属性:

波特率 = 9600

奇偶校验 = 无

StopBits = 一

    private byte[] ReadBytesInSpicifiedLength(int length)
    {
        byte[] des = new byte[length];

        for (int i = 0; i < length; i++)
        {
            des[i] = (byte)serialPort.ReadByte();
        }

        return des;
    }

【问题讨论】:

  • 串行端口可以追溯到石器时代。波特率的传统选择是 9600 波特,它移动数据的速度不能超过每字节约 1 毫秒。您使用的端口设置当然不是一个小细节,您可以忽略这样的问题。
  • @Hans:所描述的数据速率是每秒 720 字节,相当于 9600 波特(每秒 960 字节),还有一些空间。

标签: c# serial-port


【解决方案1】:

您正在执行大量单独的 I/O 调用,这意味着大量内核转换。那些很贵。每秒无法达到 720 字节令人惊讶,但您可以通过块读取使数据处理速度提高一个数量级:

private byte[] ReadBytesWithSpecifiedLength(int length)
{
    byte[] des = new byte[length];
    serialPort.BaseStream.Read(des, 0, des.Length);
    return des;
}

如果您启用了超时,您可以获得部分读取。然后您需要执行以下操作:

private byte[] ReadBytesWithSpecifiedLength(int length)
{
    byte[] des = new byte[length];
    int recd = 0;
    do {
        int partial = serialPort.BaseStream.Read(des, recd, length - recd);
        if (partial == 0) throw new IOException("Transfer Interrupted");
        recd += partial;
    } while (recd < length);
    return des;
}

BaseStream 的好处在于它还支持异步(通过ReadAsync)。这就是新的 C# 代码应该使用的。

【讨论】:

  • 感谢您的帮助。我试过了,它的性能更好。
  • @Ben Voigt 您是否完成了您在 Sparx Engineering 开始的系列博客系列?我正在尝试通过拼凑各种示例(包括您的示例)来构建一个有效的 COM 端口实现。如果您有一个工作示例,我可以用作参考,那对我来说将是一个真正的节省时间。
  • @MattDavis:我没有时间写更多文章;我们的博客软件开始吞噬内容,这真的让我失去了动力。但我仍然在这里回答关于 SO 的串口问题。我绝对推荐使用 BaseStream 属性上可用的 async/await 和 ReadAsync 函数。
  • 谢谢,@BenVoigt。我们的应用程序专注于数据收集,因此我熟悉您描述的许多概念,例如成帧、部分消息等。我已经为我们基于以太网的收集器编写了大部分处理逻辑,但这是我第一次涉足连环世界。 FWIW,感谢您在 Sparx 博客和 SO 上提供的指导。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-19
  • 2012-02-23
  • 1970-01-01
  • 2011-04-27
相关资源
最近更新 更多