
Want to save data that lasts even when power is off? Then you need to interface EEPROM with Arduino using SPI. In fact, EEPROM (Electrically Erasable Programmable Read-Only Memory) lets you store settings, logs, or user data permanently. Moreover, using SPI (Serial Peripheral Interface) makes communication fast and simple. So, if you’re building a weather logger, a smart thermostat, or any project that needs memory, this guide is for you.
This beginner-friendly tutorial shows you how to connect a 25AA160A SPI EEPROM to an Arduino Uno, write a message, and read it back. Therefore, you’ll learn hardware wiring, SPI commands, and real code that works. Let’s turn your Arduino into a data-saving machine!
Why Interface EEPROM with Arduino Using SPI?
Arduino’s built-in memory (SRAM) disappears when you unplug it. But EEPROM keeps data forever—even without power. Consequently, it’s perfect for storing Wi-Fi passwords, sensor calibrations, or high scores in a game.
SPI is the best way to talk to external EEPROM chips. It’s faster than I2C and uses dedicated hardware pins on the Arduino. As a result, you get reliable, high-speed data transfer with minimal code. Additionally, SPI supports multiple devices, so you can add more memory later.
This project teaches core embedded skills: chip selection, command protocols, and non-volatile storage. So, it’s not just about saving “Hello”—it’s about building systems that remember.
Parts Needed to Interface EEPROM with Arduino
You only need a few basic parts. First, use an Arduino Uno or any compatible board. Second, get a 25AA160A SPI EEPROM—or any similar SPI EEPROM like 25LC256. Third, prepare a breadboard and jumper wires for clean connections.
Also, install the Arduino IDE on your computer. The SPI.h library is built-in, so no extra downloads are needed. Finally, connect your Arduino with a USB cable for power and programming.
💡 Tip: Check your EEPROM’s datasheet. Some chips use slightly different pin names, but the SPI signals (CS, SCK, SI, SO) are standard.
EEPROM Pin Functions Explained
Before wiring, understand the key EEPROM pins. The 25AA160A has eight pins, but only six matter for this project. VCC and GND provide power. The SPI pins handle communication. Two special pins control safety and timing.
Write Protect (WP): This pin locks the memory. Connect it to GND to allow writing (as we do here). Connect it to 5V to make the EEPROM read-only—great for protecting firmware.
Hold (HOLD): This pin pauses SPI communication without deselecting the chip. For normal operation, tie it to 5V. Only pull it LOW if you need to interrupt a transfer—rare in simple projects.
The other pins—CS, SCK, SI, SO—are the core of SPI. We’ll connect them next.
How to Wire EEPROM to Arduino SPI
Wiring is simple if you follow the SPI map. The Arduino Uno has fixed SPI pins, so use them exactly as listed. First, connect VCC on the EEPROM to 5V on the Arduino. Then, link GND to GND.
Now, connect the SPI signals: CS (Chip Select) → Pin 10 SCK (Serial Clock) → Pin 13 SI (Serial Input / MOSI) → Pin 11 SO (Serial Output / MISO) → Pin 12 These are the hardware SPI pins—don’t change them unless you use software SPI (which is slower).
Finally, wire the control pins: WP (Write Protect) → GND (to enable writing) HOLD → 5V (for normal operation) Double-check all connections before powering up. A wrong wire can cause communication failure—but won’t damage the chip.
Key SPI Commands for EEPROM
The EEPROM listens for command bytes over SPI. Each command tells it what to do. You must send these before any data transfer. Here are the essential ones:
0x06 (WRITE_ENABLE): Unlocks write operations. Always send this before writing. 0x04 (WRITE_DISABLE): Locks the chip again—good for safety. 0x02 (WRITE_DATA): Starts a write to a memory address. 0x03 (READ_DATA): Starts a read from a memory address. 0x05 (RDSR): Reads the Status Register (checks if write is busy). In this project, we use WRITE_ENABLE, WRITE_DATA, and READ_DATA. The others are for advanced control.
Arduino Code to Interface EEPROM with SPI
// Define pin connections
#include // Include the SPI library
// Define the Chip Select pin for the EEPROM
const int CS_PIN = 10;
// EEPROM Instruction Set Opcodes
#define WRITE_ENABLE 0x06 // Set Write Enable Latch
#define WRITE_DISABLE 0x04 // Reset Write Enable Latch
#define READ_DATA 0x03 // Read Data from Memory Array
#define WRITE_DATA 0x02 // Write Data to Memory Array
#define RDSR 0x05 // Read Status Register
#define WRSR 0x01 // Write Status Register
void setup() {
Serial.begin(9600); // Initialize serial communication
// Set the CS pin as an OUTPUT and keep it HIGH (EEPROM deselected)
pinMode(CS_PIN, OUTPUT);
digitalWrite(CS_PIN, HIGH);
SPI.begin(); // Initialize the SPI bus
Serial.println("EEPROM Initialized. WP connected to GND, HOLD connected to 5V.");
// Enable writing to the EEPROM
enableWrite();
// Write a string to address 0x00
writeEEPROM(0x00, "Hello EEPROM");
delay(10); // Short delay after write operation
// Read the string back from address 0x00
char buffer[20]; // Buffer to store the read data
readEEPROM(0x00, buffer, 12); // Read 12 characters
Serial.println("Read from EEPROM:");
Serial.println(buffer); // Print the read string
}
void loop() {
// The loop is empty as the demonstration code runs only once in setup()
}
// Function to enable write operations on the EEPROM
void enableWrite() {
digitalWrite(CS_PIN, LOW); // Select EEPROM
SPI.transfer(WRITE_ENABLE); // Send WRITE_ENABLE command
digitalWrite(CS_PIN, HIGH); // Deselect EEPROM
}
// Function to write data (string) to a specified EEPROM address
void writeEEPROM(uint16_t address, const char* data) {
digitalWrite(CS_PIN, LOW); // Select EEPROM
SPI.transfer(WRITE_DATA); // Send WRITE_DATA command
// Send 16-bit address (MSB first)
SPI.transfer((address >> 8) & 0xFF); // High byte of address
SPI.transfer(address & 0xFF); // Low byte of address
// Send the data bytes
for (size_t i = 0; i < strlen(data); i++) {
SPI.transfer(data[i]);
}
digitalWrite(CS_PIN, HIGH); // Deselect EEPROM
delay(5); // A small delay is often needed after a write operation
}
// Function to read data (string) from a specified EEPROM address
void readEEPROM(uint16_t address, char* buffer, size_t length) {
digitalWrite(CS_PIN, LOW); // Select EEPROM
SPI.transfer(READ_DATA); // Send READ_DATA command
// Send 16-bit address (MSB first)
SPI.transfer((address >> 8) & 0xFF); // High byte of address
SPI.transfer(address & 0xFF); // Low byte of address
// Read data bytes
for (size_t i = 0; i < length; i++) {
buffer[i] = SPI.transfer(0xFF); // Send dummy byte (0xFF) to clock in data
}
buffer[length] = '\0'; // Null-terminate the string
digitalWrite(CS_PIN, HIGH); // Deselect EEPROM
}
How the EEPROM SPI Code Works
The code starts by including SPI.h—the standard Arduino library for SPI communication. Then, it defines CS_PIN as 10, which controls chip selection.
In setup(), Serial Monitor starts at 9600 baud. Pin 10 becomes an output and stays HIGH (deselected). SPI.begin() activates the hardware SPI bus. Then, the code prints a startup message.
Next, enableWrite() sends the 0x06 command to unlock writing. After that, writeEEPROM(0x00, “Hello EEPROM”) stores the string at memory address 0. A short delay ensures the write finishes.
Then, readEEPROM(0x00, buffer, 12) fetches 12 characters from the same address. The result prints to the Serial Monitor. If you see “Hello EEPROM,” your EEPROM works perfectly!
Testing Your EEPROM SPI Setup
After uploading the code, open the Serial Monitor. Set the baud rate to 9600. You should see: “EEPROM Initialized…” “Read from EEPROM:” “Hello EEPROM” This confirms data was written and read correctly.
Now, unplug the Arduino and plug it back in. Upload the code again—but comment out the writeEEPROM line. If “Hello EEPROM” still appears, your data survived the power cycle! That’s the magic of EEPROM.
💡 Tip: If you see garbage or nothing, check your wiring—especially CS, SI, and SO. Also, ensure WP is tied to GND. A floating WP pin can block writes silently.
Common Mistakes When Using EEPROM with SPI
One big error is forgetting WRITE_ENABLE. The EEPROM blocks all writes by default. So, always call enableWrite() before writing—otherwise, nothing saves.
Another mistake is using the wrong CS pin. SPI hardware uses fixed pins, but CS can be any digital pin. However, if you change CS_PIN in code, update your wiring too. Also, never leave CS floating—it must be HIGH when idle.
Also, some users skip the delay after writing. EEPROMs need a few milliseconds to store data. Without delay(5), the next command might fail. So, always add a small pause after writes.
Finally, don’t exceed the EEPROM’s page size in one write. The 25AA160A allows 32-byte pages. Writing more than that in one go may wrap to the next page—causing data corruption. For strings under 20 bytes, you’re safe.
How to Expand Your EEPROM Project
Once this works, try new ideas. First, store sensor readings every minute. Use a real-time clock (RTC) to timestamp each entry. This creates a data logger that survives power loss.
Second, save user settings—like brightness level or alarm time—in EEPROM. When the Arduino boots, it loads these values instantly. This makes your project feel “smart.”
Third, interface multiple EEPROMs. Use separate CS pins (e.g., 10 and 9) to control two chips on the same SPI bus. This doubles your storage without extra complexity.
Moreover, add error checking. Read the Status Register (RDSR) to confirm writes finished before proceeding. This makes your code robust for critical applications.
Why EEPROM Matters in Embedded Systems
Volatile memory (like RAM) is fast but temporary. EEPROM is slower but permanent. Therefore, smart designs use both: RAM for running code, EEPROM for long-term storage.
Examples include: Storing Wi-Fi credentials so your IoT device reconnects automatically Saving calibration data for sensors after factory tuning Logging error codes for later diagnostics In all cases, interfacing EEPROM with Arduino using SPI gives you reliable, low-cost persistence.
Final Tips to Master EEPROM with SPI
Now that you’ve interfaced EEPROM with Arduino using SPI, keep these tips in mind. Always tie WP to GND during development. Switch it to 5V in final products to prevent accidental overwrites.
Also, organize your memory layout. Reserve address 0–10 for version info, 11–50 for settings, and 51+ for logs. This avoids data collisions as your project grows.
Finally, remember: EEPROM has a write limit (usually 1 million cycles). So, avoid writing in loop() every millisecond. Instead, write only when data changes. This extends chip life for years.
Go ahead—save your first byte, then your first string, then your first system. With EEPROM and SPI, your Arduino never forgets.







Leave a Reply