12

我目前正在开发一个项目,该项目通过串行端口将数据从 java 应用程序发送到 arduino。

我遇到的问题如下,我需要将一个整数拆分为 2 个字节,然后在 Arduino 中将它们组合成一个整数。但反过来(Arduino->java)只会给我带来麻烦。arduino 部分并不难,而且工作起来就像一个魅力,但尽管我查看了已经发布在这里的相关问题和答案,但我无法完全弄清楚如何将字节正确地组合成一个 int。

这是拒绝工作的java代码:

int in = 500;
byte[] data = new byte[2];

data[0] = (byte)(in & 0xFF);
data[1] = (byte)((in >> 8) & 0xFF);

int res = data[0] | (data[1] << 8);

我从中得到的控制台打印是:

data[0] = -12  
data[1] = 1  
res = -12

但我需要res为500!

4

4 回答 4

16

Java 使用有符号字节(C、C++、C# 使用无符号字节操作),因此您应该注意补码表示(对于负值):

int in = 500; 
byte[] data = new byte[2]; // <- assuming "in" value in 0..65535 range and we can use 2 bytes only

data[0] = (byte)(in & 0xFF);
data[1] = (byte)((in >> 8) & 0xFF);

int high = data[1] >= 0 ? data[1] : 256 + data[1];
int low = data[0] >= 0 ? data[0] : 256 + data[0];

int res = low | (high << 8);
于 2013-08-15T07:16:23.200 回答
5

问题发生在这里:

int res = data[0] | (data[1] << 8);

|运算符需要int操作数,并且正在data[0]从 abyte提升为int。但是由于两者byteint都是有符号类型,因此该提升正在将字节-12转换为整数-12.... 通过符号扩展。

最简单的解决方法是:

int res = (data[0] & 0xff) | ((data[1] & 0xff) << 8);

这里还有另一个问题。通常,您不能将 a 表示int为 2 个字节。该int类型为 32 位宽,需要 4 个字节……来表示整个范围。

于 2013-08-15T07:24:51.703 回答
3

另一种可能性是使用NIO

ByteBuffer buf = ByteBuffer.allocate(2);
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.putShort(500);
byte[] result = buf.array(); // [-12, 1]

buf = ByteOrder.wrap(result);
buf.order(ByteOrder.LITTLE_ENDIAN);
short res = buf.getShort(); // 500

这有以下优点:

  • 与 Java IO 集成 - 您不需要获取数组 - 您可以直接将其传递给通道。
  • 明确的订货规范
  • 自 Java 1.4 起它就在标准库中
于 2013-08-15T10:58:07.200 回答
-1

如果你已经使用 Guava(你应该这样做),这个问题已经解决了。

于 2013-08-15T07:53:56.543 回答