2013-08-15 13 views
11

Obecnie pracuję nad projektem, który wysyła dane z aplikacji java przez port szeregowy do Arduino.Java: Dzielenie Integer na 2 bajty, a następnie łączenie ich ponownie w Integer

Problem jaki mam jest następujący: muszę podzielić liczbę całkowitą na 2 bajty, a następnie połączyć je w liczbę całkowitą w Arduino. Ale na odwrót (Arduino-> java) tylko sprawia mi kłopoty. Część arduino nie jest tak trudna i działa jak urok, ale mimo tego, że przeglądam odpowiednie pytania & Odpowiedzi już zamieszczone tutaj, nie mogę całkiem pojąć, jak połączyć bajty poprawnie razem w int.

Oto kod Java, który po prostu nie chce pracować: print

int in = 500; 
byte[] data = new byte[2]; 

data[0] = (byte)(in & 0xFF); 
data[1] = (byte)((in >> 8) & 0xFF); 

int res = data[0] | (data[1] << 8); 

Konsola się i uzyskać z tego jest:

data[0] = -12 
data[1] = 1 
res = -12 

ale muszę res być 500!

+2

int składa się z 4 bajtów, chociaż ... – Obicere

+0

Jeśli dobrze rozumiem, chcesz zapisać 5 w 'data [0]', 0 w 'data [0]'. A co z drugim 0. Nie powinno to być "bajtem [3]"? –

+0

Problem polega na tym, że używasz 'bajtu []'. Jeśli użyjesz 'short []' lub 'int []', to będzie działało zgodnie z oczekiwaniami –

Odpowiedz

16

Java używa podpisaną bajtów (C, C++, C# pracować z niepodpisanych nich), więc należy dbać o dopełniacza reprezentacji (dla wartości ujemnych):

int in = 500; 
byte[] data = new byte[2]; // <- assuming "in" value in 0..65535 range and we can use 2 bytes only 

data[0] = (byte)(in & 0xFF); 
data[1] = (byte)((in >> 8) & 0xFF); 

int high = data[1] >= 0 ? data[1] : 256 + data[1]; 
int low = data[0] >= 0 ? data[0] : 256 + data[0]; 

int res = low | (high << 8); 
+1

Dzięki, to się udało! – DodgerThud

+1

Dzięki, najlepsza odpowiedź znalazłem. Daję +2, jeśli mogę. – justinkoh

5

Problem polega dzieje tutaj:

int res = data[0] | (data[1] << 8); 

operator | wymaga int argumentów i data[0] jest promowany z byte do int. Ale ponieważ oba typy są podpisane, to promocja zamienia bajt -12 na liczbę całkowitą .... przez rozszerzenie znaku.

Najprostszą jest taka:

int res = (data[0] & 0xff) | ((data[1] & 0xff) << 8); 

Jest jeszcze inny problem, tutaj też. Ogólnie nie można reprezentować wartości int jako 2 bajty. Typ int ma szerokość 32 bitów i wymaga 4 bajtów ... aby reprezentować cały zakres.

+0

dotyczące edycji: tak, jestem świadomy, ale nie potrzebuję całego zakresu liczby całkowitej, ponieważ liczba całkowita na Arduino to 2 bajty. Nie zamierzam wysyłać niczego większego niż to, co mogą reprezentować 2 bajty. – DodgerThud

+0

Powinieneś rozważyć użycie zamiast 'Java' short'. –

+0

Tak, to też myślałem, ale chciałem sprawdzić, czy działa również z liczbami całkowitymi. – DodgerThud

2

Inną możliwością jest po prostu użyć NIO:

ByteBuffer buf = ByteBuffer.allocate(2); 
buf.order(ByteOrder.LITTLE_ENDIAN); 
buf.putShort(500); 
byte[] result = buf.array(); // [-12, 1] 

buf = ByteOrder.wrap(result); 
buf.order(ByteOrder.LITTLE_ENDIAN); 
short res = buf.getShort(); // 500 

to mieć zalety:

  • integracja z Java IO - nie musisz odbierać tablic - możesz po prostu przekazać je bezpośrednio do kanałów.
  • Jednoznaczne określenie zamawiania
  • Jest w bibliotece standardowej ponieważ Java 1.4