2009-04-10 12 views
21

czytam 133 długość pakietu z portu szeregowego, ostatnie 2 bajty zawierają wartości CRC, wartość 2 bajty i sprawiają, że pojedyncze (krótkie myślę) przy użyciu java. to co mam zrobić,2 bajty na krótko java

short high=(-48 & 0x00ff); 
short low=80; 

short c=(short) ((high<<8)+low); 

ale nie otrzymuję poprawny wynik, jest to problem, ponieważ podpisał cenione? jak mogę rozwiązać ten problem, plz pomóż mi mam kłopoty

+0

Czy istnieje szczególny powód, dla którego używasz skrótu zamiast int? Czy twoja wartość CRC nie jest równa? – akarnokd

Odpowiedz

54

Pamiętaj, że nie musisz wiązać się w węzłach z przesunięciem bitów, jeśli nie znasz szczegółów. Można użyć ByteBuffer ci pomóc:

ByteBuffer bb = ByteBuffer.allocate(2); 
bb.order(ByteOrder.LITTLE_ENDIAN); 
bb.put(firstByte); 
bb.put(secondByte); 
short shortVal = bb.getShort(0); 

I odwrotnie, można umieścić krótki, a następnie wyciągnąć bajtów.

Nawiasem mówiąc, operacje bitowe automatycznie promują operandy co najmniej do szerokości int. Naprawdę nie ma pojęcia "nie wolno przesuwać bajtu o więcej niż 7 bitów" i innych plotek, które zdają się obracać.

+0

masz rację, to promuje int, więc zmiana o 7 jest w porządku. Ale << 32 jest niezdefiniowane, więc nic nie robi. – CookieOfFortune

+0

Uważam, że bufor "konwertujący" o rozmiarze 8192 zajmuje prawie zawsze, gdy do urządzenia podłączony jest debugger. Czy istnieje sposób na konwersję całego bufora za jednym razem? –

+1

RE: "nie musisz wiązać się w węzłach z przesunięciem bitów"; z mojego doświadczenia (a jest całkiem spora, ponieważ większość mojej kariery jest w commach), kiedy zajmujemy się protokołami komunikacyjnymi tego rodzaju, lepiej poznajcie nieco manipulacje bitowe. –

20

Konwertując wartości bajtów ze strumienia na wartości numeryczne w języku Java, należy bardzo uważać na rozszerzenie znaku. Istnieje pułapka z liczbami ujemnymi (wartości od (unsigned) 128-255).

Spróbuj tego (to działa, jeśli hi i lo są wszelkiego rodzaju całkowitą Java):

short val=(short)(((hi&0xFF)<<8) | (lo&0xFF)); 

uważam, że najlepiej jest być jednoznaczne z nawiasów w tych przypadkach.

+2

Nie potrzebujesz rzutów do int, co dzieje się niejawnie dla operacji i operacji. – starblue

7

innych odpowiedzi są OK, ale chciałbym, aby położyć nacisk na typ:

short high=(-48 & 0x00ff); 
short low=80; 

int c= ((high & 0xFF) << 8) | (low & 0xFF); 

Typ short może reprezentować wartości od -32768 do 32767. 53328 nie może być ładnie przechowywane w skrócie, użytkowania int zamiast tego pozwala na przechowywanie niepodpisanej wartości do ~ 10 Nie należy więc sprowadzać wyrażenia do wartości krótkiej, ponieważ będzie ona zawierała podpisaną wartość.

+0

Chociaż w przypadku 16-bitowych CRC potrzebujesz tylko prawidłowego wzoru bitowego; nie ma znaczenia, czy ostateczna wartość Java jest podpisana. –

+0

dziękuję, użyłem 'i 0x00FF' z pierwszej linii do konwersji niepodpisanego bajtu na krótki. na przykład ustawienie wartości 0x87 na krótką daje -121 zamiast zamierzonego 135. – wrapperapps

2

Dzieje się tak, gdy próbuje złączyć bajtów (bardzo subtelny)

byte b1 = (byte) 0xAD; 
byte b2 = (byte) 0xCA; 
short s = (short) (b1<<8 | b2); 

Powyższy produkuje 0xFFCA, co jest nie tak. Dzieje się tak dlatego, że b2 jest ujemny (typ bajtowy jest podpisany!), Co oznacza, że ​​gdy zostanie przekonwertowany na typ int dla bit-wise | operacja zostanie uzupełniona o 0xF!

Dlatego należy pamiętać, aby zamaskować-out wyściełanym bajtów tak, że będą one zdecydowanie wynosić zero:

short s = (short) (b1<<8 | b2 & 0xFF); 
0

można przekonwertować 2 bajty na krótki w bardziej czytelny i elegancki sposób.

short s = ByteBuffer.wrap(new byte[]{0x01, 0x02}).getShort(); 
// now short equals 258 

Pierwszy bajt jest najbardziej znaczącym bajtem.

Powiązane problemy