C: Little Endian

4

I am trying to send & receive data between Raspberry Pi (using C programming) & Arduino (using Arduino IDE).

Based on what I can find on the internet, it points to me that both are in little endian format.

I am sending integers between them using a serial communication (RS232) with the library "RS-232 for Linux and Windows" at teuniz.net/RS-232

Based on my knowledge, if both are in little endian format, I do not need to do any shifting on the bits. However, in my case with the codes below, there is a need for me to shift the bits read in by Arduino. I am not sure why I need to perform the bit shifting when both are little endian (in order to get the correct data). Without further ado....

C Code:

unsigned char buf[4];
int g = 100;
memcpy(buf, (char*)&g, sizeof(int));

// port 24 for ttyACM0
if(RS232_SendBuf(24, buf, sizeof(int)) == -1)
{
    // error processing here
}

Arduino Code:

long a[4];
long value = 0;

 void loop(){
   if(Serial.available()>=4){
    for(int i = 0; i < 4 ; i++){
      a[i] = Serial.read();
    }

    // Over here i need to shift the LSB of the byte received to the MSB of the long var until the MSB of byte becomes LSB of long var
    // i do not have the code which is faulty right now as its already past midnight and my group mates are already asleep so I will post again in the morning
    value += a[0];
    value += a[1] << 8;
    value += a[2] << 16;
    value += a[3] << 24;

    Serial.println(value); // now it prints out 100 correctly

    value = 0;
   }

 }

Would appreciate all help! Sorry still new to C and endian!

UPDATE: I think i know why the above is happening! Please comment below to let me know if my assumption is right/wrong!

I am sending an int value of 170 in C. 170 is 0x000000aa in HEX. When i memcpy (this is where little endian comes in), it is stored as aa 00 00 00 (LSB to MSB). So when i get the value in arduino, i will definitely need to do the shifting as an integer is read from MSB to LSB (and because there is no memory copy/read in arduino, i do not care any endian problem here).

However, as Arduino is slow in processing (it has a lot of other stuffs to calculate!!), can i make my C code such that:

int g = 170;
unsigned char buf[4];
// below line not needed anymore??
//memcpy(buf, (char*)&g, sizeof(long));

if(RS232_SendBuf(24, (char *)&g, sizeof(int)) == -1)
{ ... }

Would like to hear more so I can learn more! Looks like I got my basics wrong at the beginning when I asked this question!

c
linux
arduino
raspberry-pi
endianness
asked on Stack Overflow Mar 1, 2016 by Doe Joe • edited Mar 1, 2016 by Doe Joe

2 Answers

2

Your code looks fine to me (I haven't run it).

  • Suppose you had the integer 0xaabbccdd.
  • On the Pi, "buf" would contain dd, cc, bb, aa. They would be sent down the wire in that order.
  • On the arduino, a would also contain dd, cc, bb, aa.
  • Then you create value as (dd << 0) + (cc << 8) + (bb << 16) + (aa << 24), giving 0xaabbccdd.
answered on Stack Overflow Mar 1, 2016 by peterpi
0

You are parsing a 32 bit little endian value, not a big endian value. The first byte ends up in the least significant bits; the last byte ends up in the most significant bytes.

If you were converting a buffer which contained a big endian value, the code would look like:

uint8_t a[4];
int value = 0;
for ( int i = 0; i < 4; ++i )
{
    value << 8 * i;  // shift everything over one byte
    value += a[ i ]; // add the next byte to the LSByte
}

You see the difference?

answered on Stack Overflow Mar 1, 2016 by Rob K

User contributions licensed under CC BY-SA 3.0