【问题标题】:Byte to int conversion after serial communication between ardino and androidardino和android之间串行通信后的字节到int转换
【发布时间】:2017-08-12 22:35:37
【问题描述】:

我正在我的 Android 手机和我的 Arduino 之间传输 0 到 10000 之间的正整数。 由于串口发送的是字节数组,所以我必须将发送的字节数组转换回整数。

但是我尝试过的所有东西都会抛出一个

java.nio.BufferUnderflowException

或返回错误值(我的 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);
}

我的安卓手机显示如下:

D/SerialInputOutputManager: Read data len=1
D/UsbRequestJNI: init
D/UsbRequestJNI: close
D/UsbRequestJNI: init
I/System.out: 0x00000000 96

有人解决过类似的问题吗? 提前致谢!

【问题讨论】:

  • 如果您在使用ByteBuffer 正确发布您从Arduino 获得的字节数组后仍有问题,您可能也对Endianness 有问题。
  • 你的意思是,我必须翻转字节才能得到正确的值?
  • 是的,(不是字节,字节数组,字节本身肯定没问题),或者在你的ByteBuffer上调用order(ByteOrder.LITTLE_ENDIAN)(默认是BigEndian)。
  • 你应该开始告诉我们每个数字发送了多少字节。
  • 并举一个例子,你给出发送字节的十六进制表示,然后是接收字节。只有这样您才能立即看到它们是否被交换。

标签: java android arrays arduino data-conversion


【解决方案1】:

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

【讨论】:

  • 所以我不能写数字> 255?
  • 您将需要使用Serial.write(buf, len) 方法来写入超过1 个字节。在这种情况下,您还需要注意字节顺序。
  • 好吧,我怎么告诉java那是一个无符号字节?
  • 添加了一种读取正确无符号数字的方法。 java中的byte可以严格持有-128127,所以它转换为short来持有更高的值。
  • 如果我想要这个,例如5500,我必须使用 2^16 而不是 256?
【解决方案2】:

(我的 Arduino 发送 150,我得到 -106)!

这是预期的行为。 Java 不支持无符号字节。 -106 是一个有符号字节,对应于无符号的 150。正常的追索权是这样的:

byte b = 0x96; // b has decimal value -106
int x = b & 0xff; // x now has int value 150.

现在您可以将x 操作为正值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 2019-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多