Interfacing to External EEPROM
Overview
An external EEPROM can be useful for several different reasons. External EEPROMs allow much more data to be stored than is available on the 18F4520. In addition, EEPROM memory saves state when power is removed.
In this project, we interfaced to a Microchip EEPROM in random read/write mode. "Random" write mode specifies that the memory locations accessed do not come in any sequential form. Although one can use this mode to access data sequentially in the EEPROM, there is a different protocol structure for sequential reads that increases throughput. In this project, we only developed the random write protocol.
Circuit
We used a Microchip 24FC515 external EEPROM. (http://ww1.microchip.com/downloads/en/devicedoc/21673E.pdf)
To the right is the circuit diagram for interfacing to the 18F4520.
PIN1 and PIN2, A0 and A1 are hardware addressing bits, they correspond to 0xA0 (writing data) and 0xA1 (reading data). The first 4 bits are internally set to 1010 (A) and the second four correspond to the block of memory (0 or 1), A0 and A1 (hardware addressing we set to low in this circuit diagram) and read/(NOT write).
PIN3, A2 must be connected to high for normal operation.
PIN4, Vss is for grounding the chip.
PIN5, SDA is the serial data line. This is connected to RC4 (PIN18) on the PIC.
PIN6, SCL is the serial clock line. This is connected to RC3 (PIN34) on the PIC, this wire must be soldered on the left side of the board.
PIN7, WP is the write protect line which has two states. When connected to logic high, normal read/write operation can be performed. When this pin is set low, only read operations are permitted.
PIN8, Vcc is required to power the EEPROM.
Code
Below is the code generated to interface properly to this Microchip EEPROM. It can also be downloaded here.
/* eeprom_rand_access.c Scott McLeod 03-05-2008 This program shows how to interface to an I2C extrenal Microchip EEPROM. This code is written for random reads and writes to the EEPROM */ #include <18f4520.h> #fuses HS,NOLVP,NOWDT,NOPROTECT #use delay(clock=20000000) #use i2c(MASTER, FAST, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW) // use hardware i2c controller int8 EEPROM_WR = 0xA0; // I2C Address. 1010 0000. last bit = 0 => write command // First Nibble is fixed as 1010 (internal address); // Second Nibble is ABCD, // A = Block Set // B, C = Hardware Addresses (Configured when you Wire the CHIP) // D = (0 = write, 1 = read) int8 EEPROM_RD = 0xA1; // Same as EEPROM_WR except last bit = 1 for READ command int read = 0; int data = 128; int16 loc; int temp = 0; void rand_write(int16 address, int data) { i2c_start(); // Claim I2C BUS i2c_write(EEPROM_WR); // Tell all I2C devices you are talking to EEPROM in WRITE MODE i2c_write(address>>8); // Address High Byte (0x00 - 0x) i2c_write(address); // Address Low Byte (0x00 - 0xAA) i2c_write(data); // Data to write i2c_stop(); // Release BUS delay_ms(5); // Let EEPROM Write Data (5ms from data sheet) } int rand_read(int16 address) { i2c_start(); // Claim I2C BUS i2c_write(EEPROM_WR); // Tell all I2C devices you are talking to EEPROM in WRITE MODE // (you are first writing to the EEPROM to set the address. Later you will read) i2c_write(address>>8); // Address High Byte (0x00 - 0x i2c_write(address); // Address Low Byte (0x00 - 0xAA) i2c_start(); // RESTART I2C BUS (necissary for microchip protocol) i2c_write(EEPROM_RD); // Tell all I2C you are talking to EEPROM in READ MODE. read = i2c_read(); // Read in the data i2c_read(0); // Read last byte with no ACK i2c_stop(); // release the bus return(read); } void main() { output_d(1); // Output a 1 for reference to start delay_ms(1000); // *Not necissary pause, just for debugging loc = 0x00; // Random Location in memory temp = 15; // Byte to write rand_write(loc, temp); // Random Write: rand_write(address, data) output_d(255); delay_ms(1000); // *Not necissary pause, just for visual purposes temp = 0; // Reset temp temp = rand_read(loc); // Random Read: rand_read(address); output_d(temp); // Output temp while(true) { } }