SerialPort数据丢失 – C#

我正在开发一个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驱动程序设置。

有任何想法吗?

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

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

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

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

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

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

我尝试以下方法:

  • 将Buffer-Size设置为至少230K字节
  • 将传入阈值设置为16K,32K或65K
  • 将此固定数据块写入文件

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

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

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

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

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

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

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