SerialPort数据丢失 - C#

时间:2009-10-20 15:09:09

标签: c# serial-port

我正在开发一个SerialPort应用程序,其中一个非常简单的部分就是给我一些问题。我只是想从端口读取一个恒定的数据流,并在它进入时将其写入二进制文件。问题似乎是速度:我的代码在我的9600波特率测试设备上工作正常,但是当被转移到115200bps的直播设备,我似乎正在丢失数据。发生的事情是在一段可变的时间之后,我错过了1个字节,这会抛弃其余的数据。我尝试了一些事情:

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    bwLogger.Write((byte)serialPort1.ReadByte());
}

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    byte[] inc = new byte[serialPort1.BytesToRead];
    serialPort1.Read(inc, 0, inc.Length);

    bwLogger.Write(inc);
}

和一些变化。我不能使用ReadLine(),因为我正在使用恒定的数据流(对吧?)。我试过摆弄缓冲区大小(serialPort1.ReadBufferSize和硬件FIFO缓冲区)。理想情况下,出于可用性目的,我会在软件方面处理此问题而不是让用户更改Windows驱动程序设置。

有什么想法吗?

6 个答案:

答案 0 :(得分:5)

如果问题似乎是您无法足够快地处理数据,那么您可以尝试对数据进行双重缓冲。

1)允许一个线程将串口读入一个缓冲区。这可能涉及将数据从端口复制到缓冲区(我不熟悉.NET)。

2)当您准备好处理传入的数据时,(在另一个线程上)使您的程序读入第二个缓冲区,当发生这种情况时,您应该将第一个缓冲区写入磁盘。

3)当第一个缓冲区写入磁盘时,将其交换回串口缓冲区,并将第二个缓冲区写入磁盘。重复过程,不断交换缓冲区。

答案 1 :(得分:4)

您可以尝试使用SerialPort对象的Handshake属性启用握手。

您必须在发件人或收件人上设置它。但是:如果你的接收器的UART缓冲区(非常小,16字节IIRC)溢出,那么可能没有别的办法。如果您无法在发件人上启用握手,则可能必须保持在9600或以下。

答案 2 :(得分:2)

我会尝试以下方法:

  • 将缓冲区大小设置为至少230K字节
  • 将传入阈值设置为16K,32K或65K
  • 将此固定数据块写入文件

我不确定这是否有所帮助,但至少应该采取框架的压力来解决经常发生的事件。

答案 3 :(得分:1)

  1. 我会检查Read(Byte> [],Int32,Int32)方法返回的字节数,并确保它符合您的预期。

  2. 确保您正在侦听端口对象上的SerialErrorReceivedEventHandler ErrorReceived事件。 RXOver错误表示您的缓冲区已满。

  3. 检查输出缓冲区的线程安全性。如果对输出缓冲区的写入不是线程安全的,则第二次写入可能会破坏第一次写入。

答案 4 :(得分:1)

你的bwLogger是BinaryWriter类吗?您可以尝试将其与BufferedStream一起使用,以使磁盘I / O无阻塞。

此外,如果您的数据包具有已知的结束字符,您可以设置SerialPort.NewLine属性以使您能够使用ReadLine / WriteLine,尽管我认为这不会产生很大的性能差异。

答案 5 :(得分:0)

我最近一直在使用的机器都发送了停止代码(在我的例子中是ASCII代码3或4)。如果您还具有此功能,则可以使用ReadTo(string)关闭SerialPort对象。