简体   繁体   English

无法在C#中读取完整的串行端口数据

[英]Not reading complete Serial Port data in C#

I'm using .Net framework 4 and create a serial port GUI application in C#. 我正在使用.Net framework 4并在C#中创建一个串行端口GUI应用程序。 In some cases, the SerialPort object (port) doesn't receive all the data (I compare it with a Mixed Signal Oscilloscope) 在某些情况下,SerialPort对象(端口)无法接收所有数据(我将其与混合信号示波器进行了比较)

For example, if the connected device sends: 例如,如果连接的设备发送:

0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09

I can receive: 我可以收到:

0x00 0x01 0x02 0x03 0x04 0x08 0x09 0x00 0x01 0x02 0x03 0x04 0x08 0x09

I tried different codes having the same issue: 我尝试了具有相同问题的不同代码:

  • Use the data received event to fill a buffer: 使用接收到的数据事件填充缓冲区:

      private void dataReceived(object sender, SerialDataReceivedEventArgs e) { while (port.BytesToRead > 0){ byte[] newBytes = new byte[port.BytesToRead]; int LengthRead = port.Read(newBytes, 0, newBytes.Length); Array.Resize(ref newBytes, LengthRead); System.Buffer.BlockCopy(newBytes, 0, buffer, positionInBuffer, newBytes.Length); positionInBuffer += newBytes.Length; } } 
  • Looping for an expected number of bytes, in this case causing the TimeoutException: 循环一个预期的字节数,在这种情况下导致TimeoutException:

      while (port.BytesToRead < expectedSize) { System.Threading.Thread.Sleep(10); waitingLoop++; if (waitingLoop > TimeOut) // wait for a 1s timeout throw new TimeoutException(); } newBytes = new byte[expectedSize]; LengthRead = port.Read(newBytes, 0, newBytes.Length); if (LengthRead != newBytes.Length) throw new TimeoutException(); // or any exception, doesn't matter... 

I tried to change the ReadBufferSize size, the timeout info,... but nothing works. 我试图更改ReadBufferSize的大小,超时信息等,但是没有任何效果。 Any ideas? 有任何想法吗?

There are subtle mistakes in this code. 此代码中有细微的错误。 The first snippet's Array.Resize() does nothing, maybe buffer needs to be resized instead? 第一个代码段的Array.Resize()什么都不做,也许需要调整缓冲区的大小吗? The second snippet bombs on a TimeoutException when more bytes were received than expectedSize . 当比expectedSize收到上一个TimeoutException第二个片段炸弹多个字节。 Which is certainly possible and not a timeout problem. 这肯定是可能的,而不是超时问题。

But I think the real problem is what you do with the array outside of this code. 但是我认为真正的问题是您在代码之外如何处理数组。 In general, calling SerialPort.Read() only gets you a couple of bytes. 通常,调用SerialPort.Read()只会得到几个字节。 Serial ports are slow. 串行端口很慢。 You need some kind of protocol to know when a 'full' response is received. 您需要某种协议来知道何时收到“完整”响应。 A very common (non-binary) one is simply terminating the response with a line-feed. 一种非常常见的(非二进制)方法是简单地以换行符终止响应。 Then you'd just use ReadLine() in the DataReceived event handler. 然后,您只需在DataReceived事件处理程序中使用ReadLine()。 It isn't obvious what the proper approach would be in your case. 目前尚不清楚哪种方法适合您的情况。

Also implement the ErrorReceived event. 还实现ErrorReceived事件。 It will tell you when something bad happened, like SerialError.Overrun or RXOver, errors that also make bytes disappear. 它会告诉您什么时候发生了不好的事情,例如SerialError.Overrun或RXOver,这些错误也会使字节消失。

尝试在串行端口上配置软件(XON / XOF)或硬件(例如RTS / CTS)握手,以匹配正在传输的设备的配置。

Thanks for the answers. 感谢您的回答。

Actually I have some kind of protocol in the serial data. 实际上,我在串行数据中有某种协议。 It's something like: 就像这样:

<ID><SIZE><DATA....><CHECKSUM>

I usually correctly get the ID, the SIZE and then I listen for the expected 'size' data bytes (size is less than 1000 and the serial port running at 115200, so it should be a short time). 通常,我通常会正确获取ID,SIZE,然后侦听预期的“大小”数据字节(大小小于1000,串行端口运行在115200,因此时间应该很短)。 But when I wait for them, for example with the 2nd code (waiting loop), they never come up on my C# code even if they are really passing thought the serial line (checked with the scope). 但是,当我等待它们时,例如使用第二个代码(等待循环),即使它们确实通过了串行线(已与范围检查),它们也从未出现在我的C#代码上。 Still running the 2nd code, I got the 1st TimeOutException (on the waiting loop) which means I don't receive all the data within the 1s (also tried to increase to 5s). 仍在运行第二个代码,我得到了第一个TimeOutException(在等待循环中),这意味着我没有在1s内收到所有数据(也试图将其增加到5s)。 So the error is catch before going to the SerialPort.Read() function. 因此,在进入SerialPort.Read()函数之前会捕获错误。

Anyway, I will check for the ErrorReceived event to check if I catch something... 无论如何,我将检查ErrorReceived事件以检查是否捕获到某些东西...

Regarding the Array.Resize() I wrote this in case the returned data of SerialPort.Read() has less bytes than the expected ones. 关于Array.Resize(),我写这是为了防止SerialPort.Read()返回的数据字节少于预期的字节数。 Buffer is pre-sized at the max size of my SerialPort buffer (4096). 缓冲区已预先设置为我的SerialPort缓冲区的最大大小(4096)。 Regarding my 2nd mistake in the code you are complitly right. 关于我在代码中的第二个错误,您完全正确。 I should better use a more appropriate exception :) 我最好使用一个更合适的例外:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM