2012-04-05 66 views
3

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

这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,0×46,的0x30,0x32
+5

您的“0位检查=> 0x30,0x31,0x30,0x30”示例背后的逻辑是什么? – 2012-04-05 08:47:52

+0

我使用win程序,向打印机发送命令,并从COM端口监视API中捕获此示例。 – smie 2012-04-05 08:50:27

+1

我们无法理解它。你能向我们展示更多可能的组合和例子吗? – adarshr 2012-04-05 08:56:15

回答

2

请注意,0x30 = ASCII中的'0'。它看起来像你对我要传递的16位十六进制的两个字节,与0-7位第一和第二8-15,也就是说你想传递的4-7位

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

我们会需要更多的数据点,可以肯定的,但这种适合你上面的例子:

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

显然没有输入检查这里 - 我假设,我们得到预期的格式输入。括号中的主要内容应该只是解析字符串中的一个十六进制数字 - 您可以重构它或者实现更强大的功能。

+0

0,1,2,3,4,5,9位检查 - 0x33 0x46 0x30 0x32 – smie 2012-04-05 09:30:22

+0

是的,这仍然适合:这是“3F02”作为一个字符串,所以它使用大写的十六进制。 – Rup 2012-04-05 09:32:37

+0

对不起,但我不介绍如何使用此代码。我的代码:\t \t int n = 0000001000111111; \t \t byte [] data = new byte [4]; \t \t数据[0] =(字节)((N >> 4)& 0xf); \t \t数据[1] =(字节)(N & 0xf); \t \t数据[2] =(字节)((N >> 12 )& 0xf); \t \t数据[3] =(字节)((N >> 8)& 0xf); \t \t对(INT I = 0; I <4; ++ⅰ){ \t \t数据[I] + =(数据[i] <10)?'0':('A' - 10); \t \t} ...结果:{0x34},{0x39},{0x39},{0x32} – smie 2012-04-05 09:46:19

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的数据包时得不到的)把它们分成一个字节)。

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 所以我不知道为什么你会使用,而不是仅仅为0x00的0x30 ...

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,...被检查 };

private 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"; 
} 

如果你的位都在位集合,然后更改环路成一个for循环索引,并与.get(i)检查第i位 - 如果它被设置,然后发送到BYTES_TO_SEND[i] COM端口。