Consider that I've just pulled three bytes in from a 24 bit ADC. The datasheet tells me:

The ADS1246/7/8 output 24 bits of data in binary twos complement format. The least significant bit (LSB) has a weight of (VREF/PGA)/(223 – 1). The positive full-scale input produces an output code of 7FFFFFh and the negative full-scale input produces an output code of 800000h.

My three bytes are in a byte array:

```
byte data[3]
SPI.transfer(0x12);
data[0] = SPI.transfer(0x0);
data[1] = SPI.transfer(0x0);
data[2] = SPI.transfer(0x0);
```

And now I wish to combine the bytes to form a regular long.

I know I can use:

```
unsigned long n = data[2]|(data[1]<<8)|(data[0]<<16);
```

to combine them, but my results are weird on account (I believe) that the bytes are in twos compliment.

LarryD
January 18, 2016, 11:57pm
2
Is data[0] the MSB

Make your array type unsigned long.

Try it this way:

```
unsigned long n = data[2] | (((unsigned long)data[1])<<8) | (((unsigned long)data[0])<<16);
```

MarkT
January 19, 2016, 12:17am
4
No, byte is unsigned - but you are shifting a byte left 16 bits to give zero.

The default type in an expression is int and int is 16 bits on most Arduinos.

```
unsigned long n = data[2]|(data[1]<<8)|(data[0]<<16); // data[0] is shifted 16 in a signed int context
```

Thus to shift a byte left by 16 places you must use a long variable:

```
unsigned long res = data[0] ; res <<= 8 ; // all the shifting is in unsigned long context
res |= data[1] ; res <<= 8 ;
res |= data[2] ;
```

Thus if you run this sketch (except on Due!):

```
void setup()
{
Serial.begin (115200) ;
byte data[3] ;
data[0] = 0x81 ;
data[1] = 0x82 ;
data[2] = 0x83 ;
unsigned long n = data[2]|(data[1]<<8)|(data[0]<<16);
Serial.println (n, HEX) ;
unsigned long res = data[0] ; res <<= 8 ; // all the shifting is in unsigned long context
res |= data[1] ; res <<= 8 ;
res |= data[2] ;
Serial.println (res, HEX) ;
}
void loop()
{
}
```

it will print

```
FFFF8283
818283
```

LarryD
January 19, 2016, 12:33am
5
Maybe one instruction per line makes things more readable.

```
res = data[0] ;
res <<= 8 ;
res |= data[1] ;
res <<= 8 ;
res |= data[2] ;
```

You still need to handle the sign bit. After MarkT's second example, if the sign bit in data[0] is set, set the top result byte to 0xFF.

```
if (data[0] & 0x80)res |= 0xff000000L;
```

Now you have a signed 32-bit number.

Pete

Sorry for the delay in replying, I've been out of action for a while. But thank you very much for your answers, I've learned some things, and got the code working.

Cheers!