ardino和android串行通信后字节到int的转换
Byte to int conversion after serial communication between ardino and android
我正在我的 Android phone 和我的 Arduino 之间传输 0 到 10000 之间的正整数。
由于串行发送字节数组,我必须将发送的字节数组转换回整数。
但我尝试的所有方法都抛出
java.nio.BufferUnderflowException
或returns一个错误的值(我的Arduino发送150,我得到-106)!
我用 ByteBuffer 试过了:
@Override
public void onNewData(final byte[] data) {
runOnUiThread(new Runnable() {
@Override
public void run() {
editText.append("Read: " + ByteBuffer.allocate(4).put(data).getInt());
}
});
}
并且我尝试了较小的值 255(我之前提到的 150):
@Override
public void onNewData(final byte[] data) {
runOnUiThread(new Runnable() {
@Override
public void run() {
editText.append("Read: " + new Byte(data[0]).intValue());
}
});
}
Arduino 发送以下内容:
uint16_t iSend = 150;
void loop() {
Serial.write(iSend);
delay(1000);
}
我的 android phone 内容如下:
D/SerialInputOutputManager: Read data len=1
D/UsbRequestJNI: init
D/UsbRequestJNI: close
D/UsbRequestJNI: init
I/System.out: 0x00000000 96
有没有人解决过类似的问题?
提前致谢!
Serial.write(iSend);
- 根据 documentation 此方法接受一个字节,因此调用此方法只会发送一个字节。很明显,这是从数据数组的长度发生的。 (data len=1
).
然后您尝试从字节缓冲区读取一个整数,这需要 4 个字节,但 data
输入只会提供一个字节。
简而言之,您输入的唯一有效调用是 ByteBuffer.wrap(data).get()
。
最后关于(my Arduino sends 150, I get -106)!
,这个数字在arduino上存储为uint16_t
。这是一个无符号数,而 java 只处理有符号数。这意味着该字节在到达 java 端时被解释为带符号字节。 0x96
在解释为有符号字节时是 -106
。
要解释 java 中的无符号字节,您可以使用以下代码将其强制转换为短整数:
short readAsUnsigned(byte b) {
short tmp = (short) b;
if (tmp < 0) {
tmp += 256;
}
return tmp;
}
打印 readAsUnsigned(ByteBuffer.wrap(data).get())
然后应该打印 150
(my Arduino sends 150, I get -106)!
这是预期的行为。 Java 不支持无符号字节。 -106 是一个有符号字节,对应于无符号的 150。正常的追索是这样的:
byte b = 0x96; // b has decimal value -106
int x = b & 0xff; // x now has int value 150.
现在您可以将 x
操作为正值。
我正在我的 Android phone 和我的 Arduino 之间传输 0 到 10000 之间的正整数。 由于串行发送字节数组,我必须将发送的字节数组转换回整数。
但我尝试的所有方法都抛出
java.nio.BufferUnderflowException
或returns一个错误的值(我的Arduino发送150,我得到-106)!
我用 ByteBuffer 试过了:
@Override
public void onNewData(final byte[] data) {
runOnUiThread(new Runnable() {
@Override
public void run() {
editText.append("Read: " + ByteBuffer.allocate(4).put(data).getInt());
}
});
}
并且我尝试了较小的值 255(我之前提到的 150):
@Override
public void onNewData(final byte[] data) {
runOnUiThread(new Runnable() {
@Override
public void run() {
editText.append("Read: " + new Byte(data[0]).intValue());
}
});
}
Arduino 发送以下内容:
uint16_t iSend = 150;
void loop() {
Serial.write(iSend);
delay(1000);
}
我的 android phone 内容如下:
D/SerialInputOutputManager: Read data len=1
D/UsbRequestJNI: init
D/UsbRequestJNI: close
D/UsbRequestJNI: init
I/System.out: 0x00000000 96
有没有人解决过类似的问题? 提前致谢!
Serial.write(iSend);
- 根据 documentation 此方法接受一个字节,因此调用此方法只会发送一个字节。很明显,这是从数据数组的长度发生的。 (data len=1
).
然后您尝试从字节缓冲区读取一个整数,这需要 4 个字节,但 data
输入只会提供一个字节。
简而言之,您输入的唯一有效调用是 ByteBuffer.wrap(data).get()
。
最后关于(my Arduino sends 150, I get -106)!
,这个数字在arduino上存储为uint16_t
。这是一个无符号数,而 java 只处理有符号数。这意味着该字节在到达 java 端时被解释为带符号字节。 0x96
在解释为有符号字节时是 -106
。
要解释 java 中的无符号字节,您可以使用以下代码将其强制转换为短整数:
short readAsUnsigned(byte b) {
short tmp = (short) b;
if (tmp < 0) {
tmp += 256;
}
return tmp;
}
打印 readAsUnsigned(ByteBuffer.wrap(data).get())
然后应该打印 150
(my Arduino sends 150, I get -106)!
这是预期的行为。 Java 不支持无符号字节。 -106 是一个有符号字节,对应于无符号的 150。正常的追索是这样的:
byte b = 0x96; // b has decimal value -106
int x = b & 0xff; // x now has int value 150.
现在您可以将 x
操作为正值。