1
\$\begingroup\$

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??

\$\endgroup\$
  • \$\begingroup\$ Write the first 8 bits first, then the second 8 bits? Or are you asking for actual code to be written for you? \$\endgroup\$ – PlasmaHH Jun 30 '15 at 13:20
  • \$\begingroup\$ Are you sure a long int is only 16 bits? \$\endgroup\$ – JimmyB Jun 30 '15 at 13:37
  • \$\begingroup\$ @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... \$\endgroup\$ – Adam Lawrence Jun 30 '15 at 17:39
5
\$\begingroup\$

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;
\$\endgroup\$
  • \$\begingroup\$ I was tempted to start gibbering about unions, but this isn't the moment, is it? ;-) \$\endgroup\$ – Asmyldof Jun 30 '15 at 13:37
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ – Nick Johnson Jun 30 '15 at 13:38
  • \$\begingroup\$ I know, but unions are awesomesauce :-D \$\endgroup\$ – Asmyldof Jun 30 '15 at 13:42
  • \$\begingroup\$ 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. \$\endgroup\$ – AaronD Jun 30 '15 at 19:03
3
\$\begingroup\$
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.

\$\endgroup\$
1
\$\begingroup\$

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;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.