我目前正在开发一个项目,通过串口将数据从java应用程序发送到arduino。
我遇到的问题如下,我需要将一个Integer拆分为2个字节,然后将它们组合成Arduino中的Integer。但另一种方式(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!
答案 0 :(得分:16)
Java使用签名字节(C,C ++,C#与 unsigned 操作),因此您应该处理补充表示(对于负值):
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);
答案 1 :(得分:5)
问题出在这里:
int res = data[0] | (data[1] << 8);
|
运算符需要int
个操作数,而data[0]
正在从byte
升级为int
。但由于byte
和int
都是签名类型,因此该促销通过符号扩展将字节-12
转换为整数-12
....
最简单的解决方法是:
int res = (data[0] & 0xff) | ((data[1] & 0xff) << 8);
这里还有另一个问题。通常,您不能将int
表示为2个字节。 int
类型为32位宽,需要4个字节...来表示整个范围。
答案 2 :(得分:2)
另一种可能性就是使用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
这有以下优点:
答案 3 :(得分:-1)
如果你已经使用了番石榴(你应该这样做),this problem is already solved.