MPLABX: ¿Cómo leer/escribir 4 bytes enteros sin firmar en EEPROM?

Mi pregunta parece simple, pero aún así perdí mi camino para resolver el problema. La discusión podría mostrarme el camino.

Estoy usando el microcontrolador Pic16f877A para escribir EEPROM usando I2C (1 byte a la vez). Necesito escribir un valor entero de 4 bytes (digamos 4284967295 ~ 0xFF67697F). Quiero escribir este valor en la EEPROM y leer este valor de la EEPROM cuando sea necesario. No puedo encontrar las mejores formas posibles de escribir/leer este valor.

Intenté acercarme de la siguiente manera:

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

pero perdí el camino. Y la referencia, el enlace y su orientación serán apreciados.

¡¡¡¡¡¡¡Gracias de antemano!!!!!!!

La hoja de datos del producto correspondiente contiene un código de ejemplo valioso: ww1.microchip.com/downloads/en/DeviceDoc/39582C.pdf (página 35). Si algo no está claro, pregunte qué específicamente. EDITAR: Ah, entendí mal la pregunta. Afortunadamente, dos respondedores rápidos ya resolvieron el problema por ti.

Respuestas (3)

Un problema es que no está cambiando los bits a medida que los lee en el resultado y, dependiendo del compilador, es unsigned intposible que no sea lo suficientemente grande para un valor de 32 bits. El siguiente código es de un proyecto que no es de Microchip, pero debería mostrarle una idea. Usar el stdint.hencabezado en sus proyectos generalmente es una buena idea porque puede ver fácilmente el tamaño de los tipos de datos y no confiar en los tamaños dependientes del compilador.

#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;
}
Para mi solución con CodeVisionAVR, funciona usando [&0xFF] después de TODOS los cambios (datos&0xFF, datos>>8&0xFF, datos>>16&0xFF y datos>>24&0xFF)
Ese código provino de un proyecto en el que el valor era de 8 bits, por lo que se truncaría, pero gracias, valió la pena actualizarlo para hacerlo más genérico porque ese no es un comportamiento garantizado entre compiladores y bibliotecas.

Una solución simple es usar a unionpara redefinir su unsigned longa 4 bytes (tenga en cuenta que unsigned intsolo tiene 2 bytes en 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;
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++;

}