# Breaking a 16-bit long int to write into eeprom?

I am writing data to eeprom AT24C16 using PIC microcontroller pic18f4520. Every address of this eeprom can hold 8-bits while I am using long int's to store data that are 16-bit in size. How to break long int into 2 8-bit parts to write them and how to get them back together after reading from eeprom??

• Write the first 8 bits first, then the second 8 bits? Or are you asking for actual code to be written for you? Jun 30 '15 at 13:20
• Are you sure a long int is only 16 bits? Jun 30 '15 at 13:37
• @HannoBinder He said that he was using a long int to store 16 bits of data. He could be not using the other 16 bits and still be 100% correct in his statement. Inefficient, sure, but still correct... Jun 30 '15 at 17:39

In C, you can use bit-shift and masking to extract each byte of a longer number:

lower_8bits = value & 0xff;
upper_8bits = (value >> 8) & 0xff;


And you can 'reassemble' the number from bytes by doing the reverse:

value = (upper_8bits << 8) | lower_8bits;

• I was tempted to start gibbering about unions, but this isn't the moment, is it? ;-) Jun 30 '15 at 13:37
• @Asmyldof It's tempting, but a good compiler will optimise bit shifting snippets to just a read of the relevant byte, without requiring you to worry about endianness. Jun 30 '15 at 13:38
• I know, but unions are awesomesauce :-D Jun 30 '15 at 13:42
• Some compilers are stupid enough to actually shift-by-8 and [OR/AND], exactly as stated in the source code, even on an 8-bit chip with all optimizations turned on. I've used unions and pointer notation to get around this, depending on how often I need to access each variable that way. Jun 30 '15 at 19:03
long int my16bitdata = 0xEA51;

int MSB, LSB;

MSB = (my16bitdata>>8) & 0xFF;
LSB = my16bitdata & 0xFF;


In this case the outcome would be:

MSB = 0xEA


and

LSB = 0x51


Explaination:

By perfoming a bit shift(>>) operation on the 16 bit value, we can slide the upper bits down to the lower section. All 8 of them. We then do a bitwise AND (&) with a 0xFF to apply that value to the 8 bits available in the 'int'.

For the lower 8 bits (LSB), no bit shift is required so we can just do the bitwise AND to get the data we need.

A higher level approach that lets the compiler do the shifting would look like this:

typedef union Int16
{
int data;
struct
{
unsigned char lsb;
unsigned char msb;
}bytes __attribute__ ((packed));
}Int16 __attribute__ ((packed));
#define MSB bytes.msb
#define LSB bytes.lsb

Int16 myInt;
unsigned char msb, lsb;

myInt.data = 0x1234;
msb = myInt.MSB;
lsb = myInt.LSB;