2015-12-06 3 views
5

Ich habe eine wirklich seltsame Widersprüchlichkeit.
Ich bereite mich auf das Lesen von Binärdateien auf Arduino (für einen Midi-Player, falls Sie interessiert waren). Wenn ich versuche, 4 Bytes auf Arduino zu einem langen zu kombinieren, gibt es mir ein falsches Ergebnis.
Wenn ich jedoch den entsprechenden Code auf dem PC verwende, bekomme ich den richtigen Wert.Convert 4 Byte zu lange auf Arduino Fehler

Eingabe ist: 0x12481248 (0x12, 0x48, 0x12, 0x48) (wirklich eine zufällige Zahl).

Arduino gibt: 4680.

Code :: Blocks gibt: 306713160.

4680 die gleiche wie 0x1248 ist, und das Ergebnis, das Sie erhalten, wenn Sie einen int statt lange auf Arduino (2 Byte verwenden weggelassen).

Arduino Code:

void setup(){ 
    Serial.begin(57600); 
    char read1 = 0x12; 
    char read2 = 0x48; 
    char read3 = 0x12; 
    char read4 = 0x48; 
    unsigned long testint = read1<<24|read2<<16|read3<<8|read4; 
    unsigned long testint2 = 306713160; 
    Serial.println(testint); 
    Serial.println(testint2); 
} 

void loop(){} 

testint2 ist es zu zeigen, dass es nicht durch Serial.println verursacht wird(). Serial Monitor-Ausgang ist in der Tat:

C++ Code:

#include <iostream> 

using namespace std; 

int main(){ 
    char read1 = 0x12; 
    char read2 = 0x48; 
    char read3 = 0x12; 
    char read4 = 0x48; 
    unsigned long testint = read1<<24|read2<<16|read3<<8|read4; 
    cout << testint; 
} 

Jede Idee, was los ist?

Kennt jemand auch eine bessere/schönere Art der Konvertierung von Bytes mit Arduino/SD-Bibliothek?

+0

prüfen endianness zur Compile-Zeit: http://codereview.stackexchange.com/questions/45675/checking-endianess-at-compile-time – Rabbid76

Antwort

6

Auf Arduino, int Größe is 16 bits.

In dieser Zeile:

unsigned long testint = read1<<24|read2<<16|read3<<8|read4; 

auch wenn das Ergebnis in einem unsigned long (32 Bit) gespeichert wird, werden die bitweise Operationen auf int s getan.

Ändern Sie diese Zeile:

unsigned long testint = (unsigned long)read1 << 24 
         | (unsigned long)read2 << 16 
         | (unsigned long)read3 << 8 
         | (unsigned long)read4; 
+0

Großartig, das hat den Trick gemacht, vielen Dank! –

4

Ich würde das Ergebnis 4680 (= 0x1248) auf jeder Plattform erwarten, wo sizeof (int) = 2, und ich denke, das ist der Fall für Arduino.

Das liegt daran, dass (read1 < < 24) implizit in int konvertiert wird (nicht lang), so dass die oberen zwei Bytes verloren gehen. Yout sollte zuerst lesen * zu unsigned long zuerst konvertieren

0

Sie können auch den folgenden Code verwenden:

uint8_t data[4]; 
data[0]=read4; 
data[1]=read3; 
data[2]=read2; 
data[3]=read1; 
unsigned long testint =*(unsigned long*)(&data);