通过串行发送负整数

sending negative int over serial

本文关键字:整数      更新时间:2023-10-16

对于某些项目,我必须通过串行将Java中的有符号整数发送到微控制器上的C++程序。它适用于正整数,但负整数被包裹起来,在C++端显示为正整数。

下面是在java端发送int的函数:

void writeIntToSerial(Serial port, int number) {
  port.write(byte(number << 24));
  port.write(byte(number << 16));
  port.write(byte(number << 8));
  port.write(byte(number << 0));
}

我不只是发送原始整数,而是在有效负载前后发送一些控制字符。所有这些都很好。

接收(C++)端将输入流读取到char的缓冲数组中,然后根据流中的控制字符用状态机解释流。

将字符流转换回整数的部分是基本的位移:

int startAngle = 0;
// [...]
startAngle = (payload[0] << 24) + (payload[1] << 16) + (payload[2] << 8) + payload[3];

如前所述,它适用于正值,但也就是说,-60将转换为196(256-60)。

我意识到这个解决方案可能很琐碎,但我已经盯着这个代码看了太久。。。我迷路了。

看起来一端是在序列化float,另一端是在接收int。由于这些数据类型的内部存储方式,必然存在一些不一致性。

因此,您可以发送/接收floatint,但不要将它们混淆

这是因为要将它们求和在一起,所以它们将被符号扩展到32位。

如果你把它们加在一起,你应该会得到正确的结果。

在您的示例中,当您发送-60时,您发送的是字节

0000 0000
0000 0000
0000 0000
1100 0100

然后你把它重新组装到

0...1100 0100

这是196,所以代码运行得很好。如果你发送了一个大于255的正数,你也应该在接收端收到伪造的。这是因为在Java方面,您正朝着错误的方向移动。

我猜负载的类型是char还是unsigned char?则有效载荷[x]<lt;y将在无符号字符大小中移位,该无符号字符显然不能超过8位。如果我的假设是真的,你的代码应该读

startAngle = (static_cast<unsigned int>payload[0]) << 24) + ((static_cast<unsigned int>payload[1]) << 16) + ((static_cast<unsigned int>payload[2]) << 8) + payload[3];

好的。

在发送端,我需要右移而不是左移:

void writeIntToSerial(Serial port, int number) {
  port.write((number >> 24));
  port.write((number >> 16));
  port.write((number >> 8));
  port.write(number);
}

在接收端,这个比特移位铸造序列起到了作用:

startAngle = (static_cast<uint32_t>(payload[0]) << 24)
           | (static_cast<uint32_t>(payload[1]) << 16)
           | (static_cast<uint32_t>(payload[2]) << 8) 
           | payload[3];