2015-12-06 20 views
5

Sto avendo una strana inconsistenza.
Mi sto preparando per la lettura da file binari su Arduino (per un lettore midi, nel caso fossi interessato). Se provo a combinare 4 byte su Arduino per un lungo, mi dà un risultato sbagliato.
Tuttavia, se utilizzo il codice equivalente su PC, ottengo il valore corretto.Converti 4 byte in lungo su Arduino error

L'ingresso è: 0x12481248 (0x12, 0x48, 0x12, 0x48) (in realtà un numero casuale).

Arduino dà: 4680.

Code :: Blocks dà: 306713160.

4680 è lo stesso di 0x1248, e il risultato che si ottiene quando si utilizza un int invece che a lungo su Arduino (2 byte omessa).

codice di Arduino:

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 è quello di dimostrare che non è causata da Serial.println(). uscita Serial Monitor è infatti:

codice C++:

#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; 
} 

Qualsiasi idea di cosa sta succedendo?

Inoltre, qualcuno sa un modo migliore/più carino di convertire i byte con la libreria Arduino/SD?

+0

Controllo endianness a tempo di compilazione: http://codereview.stackexchange.com/questions/45675/checking-endianness-at-compile-time – Rabbid76

risposta

6

Su Arduino, int dimensioni is 16 bits.

In questa linea:

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

anche se il risultato è memorizzato in un unsigned long (32 bit), le operazioni bit per bit sono effettuate su int s.

Modificare questa linea a:

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

Ottimo, è stato il trucco, grazie mille! –

4

Mi aspetterei il risultato 4680 (= 0x1248) su qualsiasi piattaforma in cui sizeof (int) = 2, e penso che questo sia il caso di arduino.

Questo perché (read1 < < 24) viene convertito implicitamente in int (non lungo), quindi i due byte superiori vengono persi. Yout dovrebbe convertire la lettura * a unsigned long first

0

È inoltre possibile utilizzare il seguente codice:

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