3
\$\begingroup\$

My question looks simple but still I lost my way to get the issue resolved. Discussion might show me the way.

I am using Pic16f877A microcontroller to write EEPROM using I2C ( 1 Byte at a time ). I need to write 4Bytes integer value (lets say 4284967295 ~ 0xFF67697F). I want to write this value to the EEPROM and Read this value from EEPROM whenever needed. I am unable to find best possible ways to write/read this value.

I tried approaching following way :

unsigned int a = 4284967295;
unsigned int result1, result2, result3, result4;
result1 = (( a & 0x000000FF ) ); \\ result1 = 127
result2 = (( a & 0x0000FF00 ) ); \\ result2 = 26880
result3 = (( a & 0x00FF0000 ) ); \\ result3 = 6750208
result4 = (( a & 0xFF000000 ) ); \\ result4 = 4278190080

but lost the way. And reference, link, and your guidance will be appreciated.

Thanks in advance!!!!!!!

\$\endgroup\$
  • \$\begingroup\$ The relevant product's datasheet contains valuable example code: ww1.microchip.com/downloads/en/DeviceDoc/39582C.pdf (page 35). If something's unclear, ask what specifically. EDIT: Ah, I misunderstood the question. Luckily two quick answerers already solved the problem for you. \$\endgroup\$ – Linards Sep 21 '15 at 6:44
3
\$\begingroup\$

One problem is that you're not shifting the bits along as you read them into the result and also depending on the compiler an unsigned int might not be large enough for a 32-bit value. The following code is from a non-Microchip project but should show you one idea. Using the stdint.h header in your projects is generally a good idea because you can easily see the size of the data types and not rely on compiler dependant sizes.

#include <stdint.h>

void write_eeprom_int32(uint16_t addr, uint32_t data)
{
    write_eeprom(addr, data & 0xFF);
    write_eeprom(addr + 1, data >> 8 & 0xFF);
    write_eeprom(addr + 2, data >> 16 & 0xFF);
    write_eeprom(addr + 3, data >> 24 & 0xFF);
}

uint32_t read_eeprom_int32(uint16_t addr)
{
    uint32_t result;

    result = read_eeprom(addr + 3);
    result <<= 8;
    result += read_eeprom(addr + 2);
    result <<= 8;
    result += read_eeprom(addr + 1);
    result <<= 8;
    result += read_eeprom(addr);
    return result;
}
\$\endgroup\$
  • \$\begingroup\$ For my solution with CodeVisionAVR, it works using [&0xFF] after ALL shifting (data&0xFF, data>>8&0xFF, data>>16&0xFF, and data>>24&0xFF) \$\endgroup\$ – Oka Sep 21 '15 at 7:12
  • \$\begingroup\$ That code came from a project where the value was an 8-bit so it would be truncated, but thanks it was worth updating to make it more generic because that's not guaranteed behavior between compilers and libraries. \$\endgroup\$ – PeterJ Sep 21 '15 at 7:25
3
\$\begingroup\$

One simple solution is to use a union to redefine your unsigned long to 4 bytes (note that your unsigned int is only 2 bytes in XC8):

union
{
    uint32_t      uNumber;  // exactly 4 bytes, no larger
    unsigned char uByte[4];
} myUnion;

// write to eeprom ...
myUnion.uNumber = 4284967295;
for (unsigned char i = 0; i < 4; ++i)
{
    // write myUnion.uByte[i] to eeprom here
}

// read from eeprom ...
for (unsigned char i = 0; i < 4; ++i)
{
    // read myUnion.uByte[i] from eeprom here
}
unsigned long uNumberRead = myUnion.uNumber;
\$\endgroup\$
1
\$\begingroup\$
unsigned long int a = 4284967295;

unsigned char result[4];

result[0]=a;

result[1]=a>>8;

result[2]=a>>16;

result[3]=a>>24;

j=0;

for(i=*starting_address* ;  i<= *starting_address + 4*  ; i++)

{

  write_eeprom(i,result[j]);

  j++;

}
\$\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.