从16位创建4个字节

时间:2012-04-05 08:43:36

标签: java serial-port type-conversion byte

我有16位。在每个位中,我可以设置一些属性并发送到COM端口(财务打印机)。 例如:如果选中0位,则在检查时显示徽标。

这16位我需要转换为4个字节并发送到COM端口。 例如:如果检查0位,则4个字节将为0x30,0x31,0x30,0x30。 字节结果我得到了COM端口监控API。

我必须做什么,从16位获得4个字节?

其他例子:

  • 检查了1位 - 0x30,0x32,0x30,0x30
  • 检查了2位 - 0x30,0x34,0x30,0x30
  • 检查0和2位 - 0x30,0x35,0x30,0x30
  • 检查0和9位 - 0x30,0x31,0x30,0x32
  • 检查0,1,2,3,4,5,9位 - 0x33,0x46,0x30,0x32

4 个答案:

答案 0 :(得分:2)

注意ASCII中的0x30 ='0'。它看起来像你将16位作为两个十六进制字节发送,第0-7位是第一位,8-15位,即你要传输

  • 位4-7的十六进制数字
  • 位0-3
  • 的十六进制数字
  • 位12-15的十六进制数字
  • 位8-11的十六进制数字

我们需要更多数据点才能确定,但​​这符合上述示例:

bit 0 set encodes to string "0100" = 0x30 0x31 0x30 0x30
bit 1 set                   "0200" = 0x30 0x32 0x30 0x30
bit 2 set                   "0400" = 0x30 0x34 0x30 0x30
0+2                         "0500" = 0x30 0x30 0x30 0x30
0+9                         "0102" = 0x30 0x31 0x30 0x32
0,1,2,3,4,5,9               "3F02" = 0x33 0x46 0x30 0x32

即。在Java中,如果你有一个整数n中的位,你可能想要

String output = Integer.toHexString((n >> 4) & 0xf)
              + Integer.toHexString(n & 0xf)
              + Integer.toHexString((n >> 12) & 0xf)
              + Integer.toHexString((n >> 8) & 0xf);
byte[] data = output.toUpperCase().getBytes("ASCII");

通过字符串或

byte[] data = new byte[4];
data[0] = (byte)((n >> 4) & 0xf);
data[1] = (byte)(n & 0xf);
data[2] = (byte)((n >> 12) & 0xf);
data[3] = (byte)((n >> 8) & 0xf);
for(int i = 0; i < 4; ++i) {
    data[i] += (data[i] < 10) ? '0' : ('A' - 10);
}

避免使用字符串。

要将四个字节解析回单个int,您可以使用

int bits = (((data[0] & 0xf) + ((data[0] >= 'A') ? 9 : 0)) << 4)
           | ((data[1] & 0xf) + ((data[1] >= 'A') ? 9 : 0))
           | (((data[2] & 0xf) + ((data[2] >= 'A') ? 9 : 0)) << 12)
           | (((data[3] & 0xf) + ((data[3] >= 'A') ? 9 : 0)) << 8);

显然这里没有输入检查 - 我假设我们以预期的格式获得输入。括号中的主要部分应该只解析字符串中的单个十六进制数字 - 如果需要,您可以重构或实现更强大的数据。

答案 1 :(得分:0)

嗯,16位是2个字节。因此,如果将这两个字节分成两半,则会得到4个字节。

基本上是

byte b = ...;

byte firstHalf = (byte)((b & 0x0F) >> 4);
byte secondHalf = (byte)(b & 0xF0);

但请注意,这基本上只是分裂,不会提供您在问题中描述的结果。正如已经指出的那样,目前还不清楚应该检查“0”位是什么以及如何获得那些0x30 0x31 0x30 0x30值(你只能将16位分成4和4的数据包。将它们分别放入一个字节中。

答案 2 :(得分:0)

不确定你的意思:

你有16位,只有2个字节,所以你可以保留前2个字节0并在最后2个字节中使用16位......

Byte1: 0000 0000
Byte2: 0000 0000
Byte3: first 8 bits of your 16 bits
Byte4: second 8 bits of your 16 bits

编辑:我不明白你是怎么得到0x30,0x30,0x31,0x30

0x代表十六进制

0x30十六进制= 0011 0000 binairy 所以我不明白为什么你会使用0x30而不只是0x00 ...

答案 3 :(得分:0)

这个问题对解释有点开放,我认为你的意思是:

  

如果已设置,我必须检查16位数据类型的每个位。如果是的话   设置,然后我必须将数据发送到COM端口。我需要发送哪些数据   取决于设置的位。再见,我需要发送的数据总是4个字节。

假设需要检查的位是Java int,即32位整数,其中高16位始终为0.我想建议使用BitSet来检查位和一个数组,用于定义设置该位时要发送的内容:

private static final byte [] [] BYTES_TO_SEND = new byte [] [] {       {0x30,0x31,0x30,0x30},//检查位#0时要发送的数据       {0x42},//检查位#1时要发送的数据   // ...如果检查位#2,#3,...则要发送的数据   };

私人OutputStream com;

private static final byte[][] BYTES_TO_SEND = new byte[][] {
    { 0x30, 0x31, 0x30, 0x30 }, // data to send if bit #0 is checked
    { 0x42 }, // data to send if bit #1 is checked
// ... data to send if bit #2, #3, ... is checked
};

private OutputStream com;

public void initializeCOMFromBits(int bits) throws IOException {
  for (byte[] toSendIfSet : BYTES_TO_SEND) {
    if ((bits & 0x1) == 0x1) { // check if the lowest bit is set
      com.write(toSendIfSet);
    }
    bits >>>= 1; // shift all bits by one to the left
    // now the lowest bit if the bit that was second-to-lowest previously
  }
  assert bits == 0 : "There should be at most " + BYTES_TO_SEND.length + " bits set in the incoming bit set";
}

如果您的位在BitSet中,则将循环更改为带索引的for循环,并使用.get(i)检查第i位 - 如果已设置,则将BYTES_TO_SEND[i]发送到COM端口。