丢弃一个数字的前10位

时间:2016-03-13 23:45:52

标签: java arduino processing

我使用串行协议将模拟输入值流(范围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位来发送数据。我的方案是:

image description

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

image description

我试过了:

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

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

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

2 个答案:

答案 0 :(得分:1)

16比特按此顺序发送(LSB)

  1. 01234567
  2. 89ABCDEF
  3. 在Java端你读它们,首先做一些数学运算,然后添加第二个字节。由于Java是大端,如果在Java中解释为数字,您现在已经有效地还原了这些位:

    89ABCDEF 01234567
    

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

    FEDCBA98 76543210
    

    我在文档中仔细检查过:

      

    如果操作数的大小超过一个字节,则将其存储在   big-endian order - 首先是高位字节。例如,未签名   局部变量的16位索引存储为两个无符号字节,   byte1和byte2,使其值为(byte1&lt;&lt; 8)|字节2。 (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来摆脱符号位扩展。

    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));
    

答案 1 :(得分:1)

为了标记这些位而不是它们的值,你从流中收到的位按顺序排在第一位:

0123456789ABCDEF

您按此顺序将它们放入短片中:

89ABCDEF01234567

按照您的尝试向右移动10位,然后将其留给您:

89ABCD

如果我理解正确,你真正想要的是:

ABCDEF

要实现这一点,你应该只向右移动8位,并按位屏蔽左边2并且:

(number >> 8) & 0xC0

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