2012-11-06 63 views
1

我正在写一个应用程序,通过串行连接接收来自远程无线电的一些输入。我目前使用SerialPort C#类来接收和发送数据,但我遇到了一些问题。我注意到我用于接收数据的函数没有正确设置缓冲区字节数组的大小。所有数据都以字节码(十六进制)发送。字节数组未被初始化为正确大小?

假设另一个节点发送103个字节的数据。通过我的代码并在“Read()”行设置断点,我看到“serialPort1.BytesToRead-1”的计算结果为103,但是byte []数组只是初始化为17.我没有解释这种行为。结果,只有前17个字节被放入数组中。继续完成这一步,触发相同的事件,这次“serialPort1.BytesToRead-1”的计算结果为85(假设由于只读取了103个字节中的前17个)

如果我硬核数据数组大小在103中,它一次完美地工作,但是目前我无法将所有数据存储在我的字节数组中,这导致了很多问题,任何人都知道为什么我的字节数组正在被初始化为这样任意大小???

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
     byte[] data = new byte[serialPort1.BytesToRead - 1]; 
     serialPort1.Read(data, 0, data.Length); 
     DisplayData(ByteToHex(data) /*+ "\n"*/); 
} 

更新:这里是新的方法,我试图isHeader是最初设置为true的布尔值(因为从包中收到的前两个字节实际上是包的长度)。

const int NUM_HEADER_BYTES = 2; 

    private void serialPort1_DataReceived(object sender,      System.IO.Ports.SerialDataReceivedEventArgs e) 
    { 
     byte[] headerdata = new byte[2]; 
     if (isHeader) 
     { 
      serialPort1.Read(headerdata, 0, NUM_HEADER_BYTES); 
      int totalSize = (headerdata[0] << 8 | headerdata[1]) >> 6; 
      serialPort1.ReceivedBytesThreshold = totalSize - NUM_HEADER_BYTES; 
      data = new byte[totalSize - NUM_HEADER_BYTES]; 
      isHeader = false; 
     } 
     else 
     { 
      serialPort1.Read(data, 0, data.Length); 
      double[][] results = ParseData(data, data.Length); 
      serialPort1.ReceivedBytesThreshold = NUM_HEADER_BYTES; 
      isHeader = true; 
      DisplayData(ByteToHex(data) /*+ "\n"*/); 
     } 
    } 
+2

你有没有想过将serialPort1.Read()方法改为serialPort1.ReadAllBytes() – MethodMan

+0

我没有。我担心的是,如果出于任何原因,在接收到新数据包之前没有及时处理数据包,整个数据包将被接收,并且我的解析函数会随着异常和不正确的数据发生。然而,我可能是错的。 – Burzum619

回答

3

BytesToRead等于在缓冲器中等待的字节数。它随着新数据的到来而不时变化,这就是你在这里看到的。

当你一步通过与调试器,这需要额外的时间,和串行数据的其余进来,而你在调试器步进,以及104

的全部价值,从而BytesToRead变化如果你知道你需要103字节,我相信设置ReceivedBytesThreshold到104将在适当的时候触发DataRecieved事件。如果你不知道你需要收到的信息的大小,你需要做其他的事情。我注意到你丢掉了一个字节(serialPort1.BytesToRead - 1),是否可以在读取数据时搜索到的消息结束字节?

+0

因此,如果他们做了像'int arraySize = serialPort1.BytesToRead - 1; byte [] data = new byte [arraySize];'这个问题会变得清晰吗? – Trisped

+1

你是对的,我已经从你刚才提到的代码中删除了“-1”。你所说的话是有道理的。由于我收到的数据包有2个字节的头部和数据包的长度,我现在正在做以下工作,它似乎工作得更好。如果这是一个有缺陷的解决方案,请随时告诉我,但现在看起来没问题。更改反映在原始帖子上。 – Burzum619

+0

为收到的每条消息更改ReceivedBytesThreshold有点不寻常,但我没有看到任何错误。作为替代,您可以将ReceivedBytesThreshold设置为2,并在循环中调用Read(),直到您收到totalSize总字节数。 –

2

当涉及到实时数据传输时,调试器将无法提供。使用调试跟踪。

顺便说一句,我会用自己的投票数据,而不是把我的信任事件。通过串行端口,这是一种可靠而可靠的方法。

编辑评论: 串行数据传输率受波特率限制。 你担心数据丢失,所以让我们来看看这些数字:

假设:

baud_rate = 19600 [bytes/sec] // it's usually *bits*, but we want to err upwards 
buffer_size = 4096 [bytes]  // windows allocated default buffer size 

因此,需要:

4096/19600 [sec] ~ 200 [ms] 

溢出缓冲区(上限) 。

因此,如果您在50 Hz进行抽样,您的安全网数量级上运行,这是一个很好的选择。在每个“样本”上,您读取了整个缓冲区。这里没有时间问题。

当然,你应该采用数字来处理你的情况,但是如果你的低带宽RF信道将导致传输速率为50 Hz不足以解决问题,我会感到惊讶。

最后编辑时间: 不用说了,如果你现在有作品,然后不要去碰它

+0

感谢您的建议。我一定会考虑这个。你是否建议创建一个计时器并以特定的时间间隔调用读取函数?我唯一的问题是,似乎发送数据的设备与我的程序之间的时间不匹配会导致一些重大问题(溢出缓冲区等)。特别是我会有点担心,因为这是一个远距离的射频通信,我不确定时序需要多准确。 – Burzum619

+0

谢谢你的优秀解释!非常感激。 – Burzum619