串行端口未读取所有数据

Serial port not reading all data

我有一个微控制器 (Arduino Uno) 运行 nanopb 正在通过线路发送 protobuf 消息。我发现在一个特定情况下,我没有收到完整的消息。我考虑了一会儿,它是微控制器,但它似乎是在 C# 端读取它。

该问题仅发生在 uint32 值大于 16. 16 或更小的情况下,并且工作正常。

我在微控制器上设置了一个非常简单的程序,以确保不是我的其他代码导致了它。本质上,它通过网络发送一个结构,其中包含一个 uint32_t 值:

//Protobuf message:
message Test { required uint32 testInt = 1 }

//Resulting struct:
typedef struct Test {
    uint32_t testInt;
}

//Serial code:
Serial.begin(115200);
pb_ostream_t ostream;

//Removed ostream setup code as it's not relevant here...

Test message;
Test.testInt = 17;
pb_encode_delimited(&ostream, Test_fields, &message);

如果我插入我的设备并使用 Termite 查看它的数据输出,我会看到以下数据(正确):

[02] [08] [11] (note Termite displays it in hex)

(也就是说消息有 2 个字节长,后面是消息起始字节,后面是 Test.testInt 十六进制值 17 - 0x11)

现在,如果我在 C# 中提出这个问题,我在阅读消息时应该看到 3 个字节,但我只看到 2 个字节。当 testInt 中的值等于或小于 16 时,它显示为三个字节,等于或大于 17,并且我只有两个:

var port = new SerialPort("COM7", 115200, Parity.None, 8, StopBits.One);
port.Handshake = Handshake.RequestToSendXOnXOff;
port.Open();
while (port.IsOpen)
{
    Console.WriteLine(port.ReadByte());
    Thread.Sleep(10);
}
port.Close();
Console.ReadLine();

Output with 16: 2 8 16
Output with 17: 2 8 17

非常感谢任何帮助,我对此不知所措=(

看起来像是一个简单的竞争条件 - 无法确保 C# 代码获得 3 个字节。它可以得到一个、两个、三个或更多。例如,如果它在 UART 缓冲区中有两个字节时开始循环,那么它将获得两个字节并输出它们。我怀疑16/17的问题只是巧合。

此外,当缓冲区中没有任何内容时,您的循环会消耗 100% CPU。这样不好。

你最好使用阻塞 SerialPort.ReadByte() 调用,获取长度字节,然后循环从串行端口读取更多字节。

此外,作为一种协议,单独使用没有 header 标记的 protobuf 消息并不是很好。如果您不同步,可能需要很长时间才能幸运地恢复同步。您可能希望在每条消息的开头添加某种 'magic byte' 或一系列魔术字节,以便 reader 可以重新同步。

您设置要使用的串口Xon/Xoff。为什么?

XON 的代码是 17。

如果您要发送二进制数据,请不要使用 Xon/Xoff。