Interfacing to External EEPROM

From Mech
Revision as of 20:48, 18 March 2008 by ScottMcLeod (talk | contribs)
Jump to navigationJump to search

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.

I2c eeprom circuit.jpg

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(25);              // Let EEPROM Write Data
}

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)
   {
   }
}