C51: Atmel EEPROM Programming Support
Information in this article applies to:
QUESTION
I have written the following EEPROM access functions for the Amtel
AT89C51CC03.
#include // CPU register definitions
// Return EEPROM Byte at address 'adr'
unsigned char Read_8bit_EEPROM (unsigned int adr) {
unsigned char v;
EA = 0;
EECON = 0x02; // enable EEPROM
v = *((unsigned char xdata *)adr); // read value
EECON = 0x00; // disable EEPROM
EA = 1;
return (v);
}
// Return EEPROM 16-bit value at address 'adr'
unsigned int Read_16bit_EEPROM (unsigned int adr) {
unsigned int v;
EA = 0;
EECON = 0x02; // enable EEPROM
v = *((unsigned int xdata *)adr); // read value
EECON = 0x00; // disable EEPROM
EA = 1;
return (v);
}
// Return EEPROM 32-bit value at address 'adr'
unsigned long Read_32bit_EEPROM (unsigned int adr) {
unsigned long v;
EA = 0;
EECON = 0x02; // enable EEPROM
v = *((unsigned long xdata *)adr); // read value
EECON = 0x00; // disable EEPROM
EA = 1;
return (v);
}
// Write EEPROM 8-bit 'val' at address 'adr'
void Write_8bit_EEPROM (unsigned int adr, unsigned char val) {
EA = 0;
EECON = 0x02; // enable EEPROM and set write bit
*((unsigned char xdata*)adr) = val; // write value
EECON = 0x50;
EECON = 0xA0;
EECON = 0x00; // disable EEPROM
EA = 1;
}
// Write EEPROM 16-bit 'val' at address 'adr'
void Write_16bit_EEPROM (unsigned int adr, unsigned int val) {
EA = 0;
EECON = 0x02; // enable EEPROM and set write bit
*((unsigned int xdata *)adr) = val; // write value
EECON = 0x50;
EECON = 0xA0;
EECON = 0x00; // disable EEPROM
EA = 1;
}
// Write EEPROM 32-bit 'val' at address 'adr'
void Write_32bit_EEPROM (unsigned int adr, unsigned long val) {
EA = 0;
EECON = 0x02; // enable EEPROM and set write bit
*((unsigned long xdata *)adr) = (val); // write value
EECON = 0x50;
EECON = 0xA0;
EECON = 0x00; // disable EEPROM
EA = 1;
}
All functions work fine in the SMALL memory model, but in the
LARGE memory model, the 32-bit access functions seem to fail.
What can be the reason for that?
ANSWER
The LARGE memory model locates automatic variables to the XDATA
memory space. The instruction EECON = 0x02 disables
the on-chip XDATA RAM, so it is no longer available. Therefore the
code may fetch unpredictable values from the overlaying EEPROM
space.
Since 32-bit access functions require additional memory (the other
functions allocate all variables to CPU registers), these functions
fail only in the LARGE memory model. As a solution to your problem,
you may use explicit memory model specifications.
// Return EEPROM 32-bit value at address 'adr'
unsigned long Read_32bit_EEPROM (unsigned int adr) small {
unsigned long v;
EA = 0;
EECON = 0x02; // enable EEPROM
v = *((unsigned long xdata *)adr); // read value
EECON = 0x00; // disable EEPROM
EA = 1;
return (v);
}
// Write EEPROM 32-bit 'val' at address 'adr'
void Write_32bit_EEPROM (unsigned int adr, unsigned long val) small {
EA = 0;
EECON = 0x02; // enable EEPROM and set write bit
*((unsigned long xdata *)adr) = (val); // write value
EECON = 0x50;
EECON = 0xA0;
EECON = 0x00; // disable EEPROM
EA = 1;
}
SEE ALSO
Last Reviewed: Thursday, February 25, 2021