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"*/);
        }
    }
4

2 回答 2

3

BytesToRead 等于缓冲区中等待的字节数。随着新数据的到来,它会时刻变化,这就是您在这里看到的。

当您使用调试器单步执行时,这需要额外的时间,并且在您单步执行调试器时会进入其余串行数据,因此 BytesToRead 更改为完整值 104。

如果您知道需要 103 个字节,我相信将ReceivedBytesThreshold设置为 104 将在适当的时间触发 DataRecieved 事件。如果您不知道需要接收的消息的大小,则需要执行其他操作。我注意到您丢弃了一个字节(serialPort1.BytesToRead - 1),这是您在读取数据时可以搜索的消息结束字节吗?

于 2012-11-06T23:01:45.320 回答
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不够大,我会感到惊讶。

最后编辑:不用说,如果你目前拥有的东西有效,那就不要碰它

于 2012-11-06T23:23:56.023 回答