串口不读取所有数据

时间:2015-09-12 01:22:56

标签: c# arduino serial-port protobuf-net

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

问题仅发生在大于16或16以下的uint32值且工作正常。

我在微控制器上设置了一个非常简单的程序,以确保它不是我的其他代码导致它在那里。基本上它通过线路发送一个结构,其中包含一个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个字节长,然后是msg起始字节,然后是十六进制的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

非常感谢任何帮助,我对这一点感到茫然=(

2 个答案:

答案 0 :(得分:1)

看起来像一个简单的竞争条件 - 没有什么可以确保C#代码获得3个字节。它可以得到一个,两个,三个或更多。比方说,当两个字节在UART缓冲区中时,它会启动循环,然后它将获得两个字节并输出它们。我怀疑16/17问题只是巧合。

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

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

此外,作为一种协议,单独使用protobuf消息而没有标题标记并不是很好。如果你不同步,可能需要很长时间才能获得幸运并恢复同步。你可能想要添加某种魔术字节'或每个消息开头的一系列魔术字节,以便读者重新获得同步。

答案 1 :(得分:1)

您将串行端口设置为使用Xon / Xoff。为什么呢?

XON的代码是17。

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