丢弃数字的前 10 位

Discard first 10 bits of a number

我正在使用串行协议将模拟输入值流(范围 0-1023)直接传输到计算机中。这就是我通常对值进行编码的方式:

sensorValue = analogRead(sensorPin);
// Numbers 0-255
buffer[++buffer_pos] = (sensorValue >> 0) & 0xff;
// Multiplies of 256, 0 - 3
buffer[++buffer_pos] = (sensorValue >> 8) & 0xff;

注意这是小端,我先发送最低有效数字。

在计算机的 java 端,我使用了稍微笨拙的算法,因为 java 不支持无符号字节:

short number = 0;
for(byte i=0; i<2; i++) {
  short received = (short)myPort.read();
  // turn unsigned to signed
  if(received<0)
    received = (short)((short)255+received);
  // first byte are just plain numbers 0-255
  if(i==0)
    number += received;
  // Second byte are multiplies of 256
  else
    number += received*256;
}

这意味着我只在流中使用了 16 位中的 10 位。我可以进一步压缩数据,但我想使用剩余的 6 位来发送数据。我的情况是:

我想丢弃前十位以获取标志:

我试过这个:

  // Remove first ten bits from number
  println("Code: "+(number>>10));

没用 - 它会为不同的大数字打印相同的值:

Too large number received: 24108
Code: 23
Too large received: 24109
Code: 23

16 位按此顺序发送 (LSB)

  1. 01234567
  2. 89ABCDEF

在您阅读它们的 Java 一侧,首先做一些数学运算将其向上移动并添加第二个字节。由于 Java 是大端,如果在 Java:

中被解释为数字,您现在已经有效地恢复了这些位
89ABCDEF 01234567

要在 Java 而不是位域中获得可用数字,您需要将其反转:

FEDCBA98 76543210

我在文档中仔细检查了这一点:

If an operand is more than one byte in size, then it is stored in big-endian order - high-order byte first. For example, an unsigned 16-bit index into the local variables is stored as two unsigned bytes, byte1 and byte2, such that its value is (byte1 << 8) | byte2. (https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html)

由于您是从位解释代码,因此需要它作为 Java 值。

输入为 Arduino 命令位:12345..F:

arduino: 47461 == 1010 0110 1001 1101 Bits 0123 4567 89AB CDEF
javaInt: 42653 == 1010 0110 1001 1101 Bits interpreted by Java
numeric: 47461 == 1011 1001 0110 0101 Bits reorderd to Java order F..0

我采用了您的方法并将其重写为使用整数来摆脱符号位扩展。

int number = 0;
// simulating arduino using bytearray stream.
ByteArrayInputStream myPort = new ByteArrayInputStream(new byte[] {(byte) 0b11011010, (byte) 0b10100101});
int received = myPort.read();
number = number | (received<<8);
received = myPort.read();
number = number | received;

System.out.println("arduino:  " + number + " == " + Integer.toBinaryString(number));

// reverse the bits to get Java understandable bit order for numeric values
int numericJavaInt = 0;
for(int i=0; i<16; i++) {
    int bit = (number & 1<<(15-i)) == 0 ? 0 : 1;
    numericJavaInt = numericJavaInt | bit<<i;
}

System.out.println("Java-Num: " + numericJavaInt + " == " + Integer.toBinaryString(numericJavaInt));

final int code = numericJavaInt >> 10;
System.out.println("6 upper bits code: " + code + " == " + Integer.toBinaryString(code));

为了标记位,而不是谈论它们的值,您从流中接收到的位按照从左到右的顺序排列:

0123456789ABCDEF

您正在按以下顺序将它们放入短裤中:

89ABCDEF01234567

按照您的尝试右移 10 位,然后您将得到以下结果:

89ABCD

如果我没理解错的话,你真正想要的是:

ABCDEF

为此,您应该只右移 8 位,并用按位和屏蔽左边的 2 位:

(number >> 8) & 0xC0

此外,为了更正负字节的符号,您应该添加 256,而不是 255。