我正在使用.Net framework 4并在C#中创建一个串口GUI应用程序。在某些情况下,SerialPort对象(端口)不会接收所有数据(我将其与混合信号示波器进行比较)
例如,如果连接的设备发送:
0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
我可以收到:
0x00 0x01 0x02 0x03 0x04 0x08 0x09
我尝试了具有相同问题的不同代码:
使用收到的数据事件来填充缓冲区:
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;
}
}
循环使用预期的字节数,在这种情况下导致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...
我试图更改ReadBufferSize大小,超时信息......但没有任何作用。 有什么想法吗?
答案 0 :(得分:4)
此代码中存在细微错误。第一个片段的Array.Resize()什么都不做,可能需要重新调整 buffer 的大小?当收到更多字节而 expectedSize 时,第二个片段会在TimeoutException上发生爆炸。这当然是可能的,而不是超时问题。
但我认为真正的问题是你在这段代码之外对数组做了些什么。通常,调用SerialPort.Read()只能获得几个字节。串口很慢。您需要某种协议才能知道何时收到“完整”响应。一个非常常见的(非二进制)只是通过换行来终止响应。然后你只需在DataReceived事件处理程序中使用ReadLine()。在你的情况下,适当的方法是不明显的。
还实现ErrorReceived事件。它会告诉你发生了什么不好的事情,比如SerialError.Overrun或RXOver,这些错误也会使字节消失。
答案 1 :(得分:2)
尝试在串行端口上配置软件(XON / XOF)或硬件(例如RTS / CTS)握手,以匹配正在传输的设备的配置。
答案 2 :(得分:0)
感谢您的回答。
实际上我在串行数据中有某种协议。它类似于:
<ID><SIZE><DATA....><CHECKSUM>
我通常正确地获取ID,SIZE然后我会监听预期的'size'数据字节(大小小于1000,串口运行在115200,所以应该是很短的时间)。 但是当我等待它们时,例如使用第二个代码(等待循环)时,它们永远不会出现在我的C#代码上,即使它们真的通过思考串行线(用范围检查)。仍在运行第二个代码,我得到了第一个TimeOutException(在等待循环上),这意味着我没有收到1s内的所有数据(也试图增加到5s)。因此,在转到SerialPort.Read()函数之前,错误是捕获。
无论如何,我会检查ErrorReceived事件以检查是否有东西......
关于Array.Resize()我写了这个,以防返回的SerialPort.Read()数据的字节数少于预期的字节数。缓冲区的大小预先设置为我的SerialPort缓冲区的最大大小(4096)。 关于我在代码中的第二个错误你是对的。我应该更好地使用更合适的例外:)