Adding Memory with i2c EEPROMs

It doesn't take long to start running out of memory in microcontroller projects - especially if the project involves storing data gathered from sensors and other inputs. Fortunately, it is easy and inexpensive to add quite a bit of data storage capacity using serial EEPROM chips. This tutorial will provide an introduction to interfacing PICAXE processors with the Microchip 24LC16B and 24LC256 i2c EEPROMs. While there are many other options, these particular EEPROMs are inexpensive and readily available from both PICAXE vendors and general electronics hobby suppliers. Additionally, their use is extremely well documented. They are the EEPROMs used in the Revolution Education AXE110 datalogger and the AXE111 memory expansion board, as well as many third party project designs.

EEPROM stands for electrically erasable programmable read-only memory. EEPROM is a non-volatile memory which means that unlike RAM, its contents will be preserved even when power is removed from the circuit. All PICAXE processors have some EEPROM built-in; it is used for both program and data storage. Microchip Technology, the manufacturer of the PIC processors on which all PICAXE microcontrollers are based, produces a large variety of serial EEPROMs for many different applications.

i2c and PICAXE

The i2c (inter-integrated circuit) protocol is a widely implemented method for moving data back and forth among integrated circuits. All of the X, X1 and X2 PICAXE parts support the i2c protocol. In i2c a potentially large number of devices are all connected via a simple two-wire serial bus. The protocol establishes master-slave relationships among the devices. Every slave device on the i2c bus is identified by a unique address. Sometimes this address is built into the IC itself, other times it is configured within the circuit design.

A typical simple configuration would have a microcontroller such as the PICAXE act as a master controlling several additional ICs such as a memory chip and a digital sensor. However, i2c is a multi-master system and it is possible to have numerous controllers acting as masters at various points in a process. It is also possible to have ICs change roles during the process. These advanced setups will be beyond the scope of this tutorial, but it is important to understand that they are possible

There are two i2c implementations on PICAXE - software and hardware. The software implementation is available on all of the parts with i2c support - X, X1, and X2. Hardware i2c is only available on the X1 and X2 parts and the manual recommends using hardware i2c on those parts. When a PICAXE controller is acting as the master on an i2c bus there will be three relevant commands. The program must first execute a command which establishes some basic criteria about the slave device such as its unique address on the bus, and the speed at which the slave can operate. Once the slave device is established, the program will execute commands to either read or write to the slave device.

The principles of software and hardware implementation are essentially the same. However, there are different commands for each implementation and hardware i2c has some capabilities not available in software - notably the ability to act as a slave on the bus. The following chart should be of some use in understanding the protocols.

Software vs. Hardware Implementations

SoftwareHardwareFunction
I2CSLAVEHI2CSETUP HI2CMASTEREstablishes the PICAXE as a master on the i2c bus and prepares
to connect with a slave device.
n/aHI2CSETUP I2CSLAVEEstablishes the PICAXE as a slave on the i2cbus.
n/aHI2CSETUP OFFStops background i2c processing
WRITEI2CHI2COUTWrites a byte or sequence of bytes to the i2c device.
READI2CHI2CIN Reads a byte or sequence of bytes from the i2c device.

The syntax of the I2CSLAVE and HI2CSETUP HI2CMASTER commands are identical - they each take three parameters:

slaveaddress is the unique identifier of the slave device. It is generally listed in binary form such as %10100111. The least significant bit (the digit furthest to the right) is used for setting the mode to read or write. This digit doesn't actually doesn't matter in PICAXE BASIC as it is handled programmatically. You will sometimes see binary addresses in spec sheets written with an "x" in that location: %1010011x. Use either 1 or 0 when executing the command on PICAXE controllers.

mode refers to the speed of transfer and is expressed using the keywords i2cfast or i2cslow. The mode is dictated by the slowest device on the bus. When using hardware i2c, the i2cfast and i2cslow keywords can be additionally modified to account for increased clock speeds - i2cfast_8 (8 MHz), i2cfast_16 (16 MHz), i2cslow_8 (8 MHz), and i2cslow_16 (16 MHz)are all valid keywords.

addresslen refers to the size of address which is either byte (keyword i2cbyte) or word (keyword i2cword). Again, the addresslen parameter is a function of the device being accessed. The address length is frequently confused with the size of the data being transferred on the bus - i2c data is always transferred in byte increments regardless of whether the length of the address is a byte or a word (two bytes).

Software i2c has the syntax:

      I2CSLAVE slaveaddress, mode, addresslen

An example of a properly formatted I2CSLAVE command might be:

    i2cslave %10101110, i2cfast, i2cbyte

Hardware i2c has the syntax:

    HI2CSETUP I2CMASTER slaveaddress, mode, addresslen

An example of a properly formatted HI2CSETUP I2CMASTER command might be:

   hi2csetup i2cmaster %10101110, i2cfast, i2cbyte

Once the required information to read and write from a slave device is established, the appropriate read and write commands can be executed. It is not necessary to execute additional I2CSLAVE or HI2CSETUP HI2CMASTER commands for every read or write. In software i2c a new I2CSLAVE command will need to be executed to change to a new slave address. In hardware i2c a new slave address can be entered as a parameter to the HI2COUT and HI2CIN commands.

When reading and writing to slave devices, the syntax for hardware and software implementation is again very similar, with the addition in hardware of the optional newslave parameter.

To read from an i2c device in software use the syntax:

   READI2C location,(variable1, variable2 ...)

To write to an i2c device in software use the syntax:

   WRITEI2C location,(variable1, variable2 ...)

Location is a optional variable or constant specifying an address on the slave device. The variables either receive the data read or contain the data to be written.

To read from an i2c device in hardware use the syntax:

  HI2CIN [newslave],location,(variable1, variable2 ...)

To write to an i2c device in hardware use the syntax:

  HI2COUT [newslave],location,(variable1, variable2 ...)

Both newslave and location variables are optional. Newslave is a new slave address for this (and all future) commands. Location is a variable or constant specifying an address on the slave device. The variables either receive the data read or contain the data to be written.

24LCxxx EEPROMs

The 24LCxxx EEPROMs are very commonly used. They are available in a variety of packages including the standard 8-pin DIP (dual inline pin) which makes them ideal for breadboard and home PCB assembly projects. A pinout diagram of the 24LCxxx DIP package is nearby.

Legs 1-3 (A0-A2) are used for setting the slave address on EEPROMs that support configurable addressing. All 24LCxxx EEPROMS have an address that begins %1010. If the EEPROM supports configurable addressing, then the A0-A2 pins are used to set the remaining three digits with A0 being the least significant (furthest to the right). If a pin is tied to ground then the digit is a zero, if the pin is tied to positive voltage then the digit is a one. If A0 were tied to positive voltage and the remaining pins tied to ground, then the address would be %1010001x

Leg 5 is the data line and leg 6 is the clock signal - these are the legs which are connected to the appropriate lines of the i2c bus. Each of the bus lines is pulled high by connecting it to positive voltage through a resistor. In typical configurations a 4.7k resistor is used, but there are times when a lower value may need to be substituted (on long bus runs for example).

Leg 7 is used for write protection. If it is tied high (connected to positive voltage) then writing to the chip is prevented, if it is tied low (connected to ground) then writing to the chip is enabled. A common configuration is to wire the pin directly to ground so that writing is always enabled. Sometimes the write protect pin is tied to an output of a PICAXE or other microcontroller in order to enable and disable writing programmatically.

The 24LC16B is a 16Kbit EEPROM organized as eight blocks of 256 x 8 bit memory - which means it will store 2048 bytes (2Kbyte) of data. The "B" series of EEPROMs are Microchip's least expensive, priced at less than $0.50 even in single quantities. A limitation of the 24LC16B and other EEPROMs with part numbers ending in "B" is that they use byte addressing which limits the internal address to 256 registers. This addressing protocol is only enough to address a single block of registers. To enable use of the full eight blocks, the 24LC16B borrows 3 of the 7 address bits from the slave address to specify the memory block and therefore the three address pins A0-A2 are not functional. The result of this limitation is that all 24LC16Bs have the same address and therefore only one chip can be used on an i2c bus. While it might seem like a small number, 2 kilobytes can often be more than enough for a project. A 24LC16B could hold two thousand sensor readings or 64 messages for a 2x16 LCD display.

When needed, the 24LC256 is a nice upgrade from the 24LC16B. The 24LC256 is a 256 Kbit (32 Kbyte) EEPROM. Like its smaller cousin it is inexpensive - less than $2.00 in single quantities and less than $1.00 in bulk. In addition to their greater capacity, the 24LC256 uses word length addressing. The configurable address lines are functional which allows up to eight devices to be included on the same bus.

When writing to either of these EEPROMS a short delay of about 10ms is necessary to complete the write cycle. It is typical to include a PAUSE 10 command after a write command to accomplish this delay. Both the 24LC16B and the 24LC256 have a page write buffer that enables multiple bytes to be written in a single operation. Use of the page buffer can dramatically improve speed and efficiency.

The 24LC16B has a 16 byte page buffer and the 24LC256 has a 64 byte page buffer. However, that does not mean that 16 or 64 bytes can always be written. Page write operations are limited to writing bytes within a single page. Page boundaries are a related to the address space of the device in question. They start at addresses that are multiples of the page size and end at addresses that are integer multiples the page size 1. Therefore on the 24LC16B with a 16 byte page, there is a page that starts at location 0 and ends at location 15, another page from 16 to 31, and another from 32 to 47, etc. Likewise on the 24LC256 with a 64 byte page, there is a page that starts at location 0 and ends at location 63, another page from 64 to 127, and another page from 128 to 191, etc.

If an HI2COUT or WRITEI2C command attempts to write across a page boundary, instead of being written to the next page the data wraps around to the beginning of the current page. Any data at the beginning of the page is overwritten. There is no warning of this overwriting, and depending on the type of data being written, it might not be immediately obvious the programming error has been made. Program code must be carefully written to prevent page write operations that would attempt to cross a page boundary.

About the Examples

The tutorial concludes with two example circuits, a PICAXE 18X with a 24LC16B, and a PICAXE 20X2 with two 24LC256 chips. The 18X is used to demonstrate software i2c implementation while the 20X2 will use the hardware commands. The pinouts of these two processors are shown below. The i2c data (sda) and clock (scl) pins on these processors are pre-defined - on the 18X they are on legs 7 and 10, while on the 20X2 they are on legs 13 and 11.

PICAXE 18X with a 24LC16B EEPROM

Pictured below is a basic schematic for a circuit interfacing a PICAXE 18X with a 24LC16B. Note in the circuit that the i2c lines are tied high with 4.7k resistors and that the write protect pin on the 24LC16B is tied low with a connection straight to ground.

This illustration shows how you might implement the circuit on a standard solderless breadboard.

Here is a little bit of sample code to show how you might apply software i2c commands to this circuit. This sample and the next both use a programming cable to send results to the terminal in the PICAXE Programming Editor. Those connections are not shown in the sample circuit.

 ;----------------------------------------------------------
 ; Test code for EEPROM demo circuit PICAXE 18X and 24LC16B
 ;----------------------------------------------------------

 #picaxe 18X

 ;---------------------------------------------------------
 ; Write a sample to block 000 - note that you can only
 ; write 16 bytes at a time to the 24LC16B buffer
 ;---------------------------------------------------------


   i2cslave %10100000, i2cfast, i2cbyte
   writei2c 0,("This sample is i")           
   pause 10                                 
   writei2c 16,("n block 000")              
   pause 10

 ;---------------------------------------------------------
 ; Write a sample to block 001
 ;---------------------------------------------------------

   i2cslave %10100010, i2cfast, i2cbyte
   writei2c 0,("This sample is i")
   pause 10
   writei2c 16,("n block 001")
   pause 10

 ;---------------------------------------------------------
 ; Read the samples back to the terminal
 ;---------------------------------------------------------


   i2cslave %10100000, i2cfast, i2cbyte
   for b0 =  0 to 26
    readi2c b0, (b1)
    sertxd (b1)
   next
   sertxd (13,10)

   i2cslave %10100010, i2cfast, i2cbyte
   for b0 =  0 to 26
    readi2c b0, (b1)
    sertxd (b1)
   next
   sertxd (13,10)



PICAXE 20X2 with two 24LC256 EEPROMs

Pictured below is a basic schematic for a circuit interfacing a PICAXE 20X2 with two 24LC256 EEPROMS. This circuit is, of course, very similar to the prior example. Note that here there are connections to the address configuration lines to enable more than one 24LC256 to be present on the i2c bus. Also of interest is the fact that only two pullup resistors are needed even when additional devices have been added to the circuit.

This illustration shows how you might implement the circuit on a standard solderless breadboard.

Here is a little bit of sample code to how you might apply hardware i2c commands to this circuit.

 ;-----------------------------------------------------------
 ; Test code for EEPROM demo circuit PICAXE 20X2 and 24LC256
 ;-----------------------------------------------------------

   #picaxe 20x2
   pause 500
 
 ;----------------------------------------------------------
 ; Write a sample to the first chip - note that the buffer
 ; on a 24LC256 can hold 64 bytes
 ;----------------------------------------------------------



   hi2csetup i2cmaster, %10100000, i2cfast, i2cword 
   hi2cout 0,("This sample is in device 000")             
   pause 10                                      

 ;----------------------------------------------------------
 ; Write a sample to the second chip - note that in hardware 
 ; i2c you don't need to issue a new setup command
 ; the new address can be a hi2cout or hi2cin parameter
 ;-----------------------------------------------------------
 
   hi2cout [%10100010], 0, ("This sample is in device 001")  
   pause 10

 ;----------------------------------------------------------
 ; Read the samples back and send them to the terminal
 ;----------------------------------------------------------
   hi2cin [%10100000],0,(b1)
   sertxd (b1)
   for b0 =  1 to 27
     hi2cin (b1)
     sertxd (b1)
   next
   sertxd (13,10)
   
   hi2cin [%10100010],0,(b1)
   sertxd (b1)
   for b0 =  1 to 27
     hi2cin (b1)
     sertxd (b1)
   next
   sertxd (13,10)





Other Articles You Might Find Enjoyable

Introduction to the PICAXE Microcontroller

Guide to PICAXE Selection

Setting Up A Differential Drive For Your PICAXE Project

Basic PICAXE Servo Interfacing

Robot Obstacle Detection and Avoidance with the Devantech SRF05 Ultrasonic Range Finder

Calculating Right Triangles with PICAXE BASIC

Understanding Variables and Symbols in PICAXE BASIC

PICAXE USB to Serial Conversion


Things to Do Here

All PICAXE Articles
Home
Links