How to interface a 47C16 EERAM with Arduino

Today we are going to wire a 2kb Microchip 47C16 serial I2C ram chip to Arduino and exploit its sequential read and write capabilities.

The 47C16 is a 5V chip, but it also exists in a 3.3V low power version, named 47L16.


A typical 8 bit microcontroller such as the ATMEGA128P has 4 kilobytes of RAM. Sometimes it’s just not good enough, and you need to have additional memory. On other occasions, you may have to share memory across more than one processor and therefore you need an external component. Microchips’ EERAM series can fit this role and it is a pretty interesting chip for many reasons:

  • Only two wires required and high speed: I2C up to 1Mhz
  • 2 KiB of RAM for the 47L16 (3.3V) and 47C16 (5V)
  • Automatically back up to EEPROM on power down
  • prototyping friendly: available in DIP, SOIC and TSSOP packages

When I was looking for a RAM integrated circuit, I thought that was exactly what I needed. But there is hardly any resource on these chips; so here we are with this how to guide!

47C16 in DIP package
47C16 in DIP package

Parts needed

  • 47C16 or 47L16 chip; available from usual retailers such as Digikey, Mouser and Farnell for US$1
  • 2 resistors for the I2C bus. 10kΩ is a good value for a standard 100Khz I2C bus. I used 5.6kΩ in my experiments to test fast mode I2C.
  • Jumper wires
  • Breadboard

Connecting the RAM chip

Wiring the chip is very simple: supply power to VCC, ground to VSS, and link SDA/SCL on your board with pullup resistors.

47CL04 47C04 47C16 47C16 pinout
The RAM chip pinout

Now you’ll notice that in the schematics below I have also grounded HS, A1 and A2; and for good reasons:

  • A high on HS triggers a replication of the RAM content to the internal EEPROM. If you intend to use the chip as just RAM, it will not be used.
  • A1/A2 are chip select: they change the I2C address of the chip. They should be grounded if you intend to have only one RAM chip. By the way, this implies you can have up to four of these on a single I2C bus (A2/A1 values of 00, 01, 10 and 11); but not a single more.
47C16 RAM connected to Arduino Uno
47C16 RAM connected to Arduino Uno

In real life:

47C16 RAM connected to an Arduino Uno. HS pin is not grounded here, which is a mistake as a floating pin can sometimes be read as logic 1. Force the pin to ground to avoid any ambiguity.
47C16 RAM connected to an Arduino Uno. HS pin is not grounded here, which is a mistake as a floating pin can sometimes be read as logic 1. Force the pin to ground to avoid any ambiguity.

Code to make it work

First and foremost, download the Serial RAM library by clicking on the link below:

Download the Serial RAM library

It’s completely open source and available as a CC-BY Creative Common License; so by all means please go ahead and take a peak at the source code.

There are two ways to read and write to memory:

  • Random access: you read/write a byte at a given address
  • Sequential access: you read/write a series of bytes at a given address

The later is a lot more efficient when it comes to speed; as you don’t have to constantly change the memory pointer. Sending a 16 bit address to retrieve 8 bit of data is over 66% of the I2C bandwidth lost to control flow. For most projects these considerations shouldn’t matter much, but it’s always a good thing to keep in mind.

Initializing the RAM chip

In one line of code:

#include <SerialRAM.h>;

SerialRAM ram;

void setup() {

begin takes optional parameters, namely A1/A2 values. By default they are set to 0 so you don’t need to specify any parameter.

Random write access:

ram.write(0x0100, 0x55); ram.write(5, 'A');

Again, very simple. The first parameter is the address, the second a byte-sized value (char, int8_t, uint8_t).

Random read access:

uint8_t buffer = 0x00; 
buffer =;

This will retrieve the byte located at address 0x100.

Sequential write:

uint8_t data[27] = "abcdefghijklmnopqrstuvwxyz"; 
//write the entire 27 bytes of data, starting from address 0x00 
ram.write(0x0000, data, 27);

Writing an array of bytes is just as simple, but you need to specify the length of the array.

Sequential read:

uint8_t data2[27]; 
//read 27 bytes from address 0x0000, data2, 27);

Again, this is a very simple operation, and you just have to make sure the array that receives the data is big enough.

Conclusion and Arduino I2C considerations

There’s a hard limit on the Arduino I2C library: you can’t read/write more than 30 bytes because the buffer is hardcoded to 32 (you may, of course, recompile the library if you so desire). Since two bytes are already used by the 16 bit address, that leaves only 30 for data.

I really struggled with this issue until I figured the Arduino library itself was the faulty one. I thought there was a problem with a noisy breadboard; and I even made my own PCB to make sure this wasn’t the case. So much time lost because I trusted the Arduino I2C library! Do not make the same mistake!