2013-08-15 11 views
11

Ich arbeite derzeit an einem Projekt, das Daten von einer Java-Anwendung über eine serielle Schnittstelle an ein Arduino sendet.Java: Integer in 2 Bytes aufteilen und dann wieder zu einem Integer

Das Problem, das ich habe, ist das Folgende, ich muss ein Integer in 2 Bytes aufteilen und dann zu einem Integer in Arduino kombinieren. Aber umgekehrt (Arduino -> Java) bereitet mir nur Ärger. Der Arduino-Teil ist nicht so schwer und funktioniert wie ein Zauber, aber trotz mir durch die relevanten Fragen & Antworten bereits gepostet hier auf, kann ich nicht ganz herausfinden, wie man die Bytes richtig zu einem int kombinieren.

Hier ist der Java-Code, der gerade zur Arbeit verweigert: von diesem

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); 
Die Konsole Ausdruck i erhalten:

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

aber ich brauche res!

+2

Ein int besteht aus 4 Bytes, obwohl der Bestellung ... – Obicere

+0

Wenn ich es richtig verstanden habe, möchten Sie 5 in 'data [0]', 0 in 'data [0]' speichern. Was ist mit den anderen 0. Sollte es nicht "Byte [3]" sein? –

+0

Das Problem ist, dass Sie ein 'byte []' verwenden. Wenn Sie ein 'short []' oder ein 'int []' verwenden, würde es wie erwartet funktionieren –

Antwort

16

Java verwendet unterzeichnet Bytes (C, C++, C# arbeiten mit unsigned sind), so dass Sie kümmern Ergänzung Darstellungen nehmen sollte (für negative Werte):

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

Danke, das hat den Trick gemacht! – DodgerThud

+1

Danke, beste Antwort, die ich gefunden habe. Ich gebe +2, wenn ich könnte. – justinkoh

5

Das Problem ist, geschieht hier:

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

Der | Bediener erfordert int Operanden und 012.327.wird von einem byte zu einem int befördert. Da sowohl byte als auch int signierte Typen sind, wird durch diese Heraufstufung das Byte -12 in die Ganzzahl -12 .... durch Vorzeichenerweiterung umgewandelt. diese

Die einfachste Lösung ist:

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

Es gibt ein anderes Problem zu hier. Im Allgemeinen können Sie keine int als 2 Bytes darstellen. Der int Typ ist 32 Bits breit und benötigt 4 Bytes ... um den gesamten Bereich darzustellen.

+0

zu Ihrer Bearbeitung: ja, ich bin mir bewusst, aber ich brauche nicht den gesamten Bereich der Ganzzahl, weil Integer auf Arduino 2 Bytes sind. Ich plane nicht, etwas größer als was 2 Bytes darstellen können, zu senden. – DodgerThud

+0

Sie sollten stattdessen einen Java-'short' verwenden. –

+0

Ja, das dachte ich auch, aber ich wollte sehen, ob es auch mit Integern funktioniert. – DodgerThud

2

Eine andere Möglichkeit ist nur NIO zu verwenden:

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 

Diese Vorteile haben:

  • Integration mit Java IO - Sie müssen die Arrays nicht erhalten - Sie können sie einfach direkt an die Kanäle übergeben.
  • Explizite Angabe
  • Es ist in der Standardbibliothek seit Java 1.4