2012-04-05 65 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端口。