INFORMACIÓN
La memoria EEPROM FT24C32A es una solución de almacenamiento no volátil compacta de 4 KB (32 Kb), almacenamiento organizado de 4096 x 8 bits. Utiliza el protocolo I²C para comunicarse. La conexion entre otros modulos puede ser via header o por conectores Qwiic.
El módulo DevLab FT24C32A es ideal para el almacenar configuraciónes como preferencias de usuario o estados del sistema que deben persistir tras un apagado; calibración de sensores, es decir, almacenarmiento de constantes y offsets de precisión; identificación como guardar números de serie únicos o direcciones MAC o registro de datos (Data Logging) como es el caso de guardar historial de errores, marcas de tiempo o eventos en sistemas embebidos e IoT.
ESPECIFICACIONES Y CARACTERÍSTICAS
- Marca: UNIT Electronics
- Pais de origen: Hecho en México
- Tipo: Modulo EEPROM
- IC: FT24C32A
- Voltaje de alimentación: 1.8V a 5.5V
- Corriente de lectura: 0.4 mA típica, 1.0 mA máxima
- Corriente de escritura: 2.0 mA típica, 3.0 mA máxima
- Memoria: 32Kb(4KB)
- Capacidad: 4096 x 8 bits (4 KB).
- Ciclos escritura: 1,000,000 , 100 años de retencion de datos
- Frecuencia de operación :
- 1Mhz @ 2.5 a 5V
- 400 kHz @ 1.8V
- Interfaz I2C
- Direcciones I2C: 0x50,0x51,0x52,0x53,0x54,0x55,0x56 y 0x57
- Compatibilidad: ESP32, Arduino, STM32, RP2040.
- Temperatura de operación: -40 °C a 85 °C.
- Dimensiones: 25.38mm x 18.51mm
- Peso: 2.91 g
DOCUMENTACIÓN Y RECURSOS
INFORMACIÓN ADICIONAL
En el siguiente test se realizara el escaneo de la memoria via I2C y autodetección, realizara operaciones secuenciales de lectura/escritura,soporte de escritura por páginas (páginas de 32 bytes), borrado completo de la EEPROM, verificación de protección contra escritura y visualización de datos en hexadecimal y ASCII; todo mediante la interfaz de comandos por Serial del IDE Arduino.
Diagrama de conexión
Para este test ocuparemos una tarjeta de desarrollo que tenga comunicacion via I2C, en nuestro caso utlizamos la Pulsa C6 con conexion via Qwiic para facilitar la conexión.

Configuraciones previas
En caso de que ocupes la tarjeta de desarrollo Pulsa C6, tendras que habilitar “USB CDC on Boot”, esta es una configuración para ESP32-S2/S3/C3 para activar el puerto USB nativo como un puerto serie virtual (COM/TTY) desde el inicio. Esta opcion se encuentra en la seccion de Herramientas (Tool), dentro del IDE de Arduino.

Código de prueba
Realizando la conexión y la configuración previa pasaremos a realizar el siguiente programa:
#include <Wire.h>
// ===== CONFIGURA TUS PINES I2C =====
#define SDA_PIN 6
#define SCL_PIN 7
// ===================================
#define EEPROM_BASE 0x50
uint8_t eepromAddr = EEPROM_BASE;
// ---------- Utilidades ----------
void eepromWaitReady(uint32_t timeout = 25) {
uint32_t t0 = millis();
while (millis() - t0 < timeout) {
Wire.beginTransmission(eepromAddr);
if (Wire.endTransmission() == 0) return;
delay(1);
}
}
bool eepromWritePaged(uint16_t mem, const uint8_t *data, size_t len, size_t page = 32) {
size_t off = 0;
while (off < len) {
size_t pageSpace = page - ((mem + off) % page);
size_t chunk = min(len - off, pageSpace);
Wire.beginTransmission(eepromAddr);
Wire.write((mem + off) >> 8);
Wire.write((mem + off) & 0xFF);
Wire.write(data + off, chunk);
if (Wire.endTransmission() != 0) return false;
eepromWaitReady();
off += chunk;
}
return true;
}
bool eepromReadSeq(uint16_t mem, uint8_t *buf, size_t len) {
Wire.beginTransmission(eepromAddr);
Wire.write(mem >> 8);
Wire.write(mem & 0xFF);
if (Wire.endTransmission(false) != 0) return false;
size_t got = 0;
while (got < len) {
size_t req = min((size_t)32, len - got);
if (Wire.requestFrom((int)eepromAddr, (int)req) != (int)req) return false;
for (size_t i = 0; i < req; i++) buf[got++] = Wire.read();
}
return true;
}
void dumpHex(const uint8_t* buf, size_t n) {
for (size_t i = 0; i < n; i++) {
if (i && i % 16 == 0) Serial.println();
Serial.printf("%02X ", buf[i]);
}
Serial.println();
}
// ---------- Comandos ----------
void cmdScan() {
Serial.println("n[I2C] Escaneando...");
bool any = false;
bool picked = false;
for (uint8_t addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
any = true;
Serial.printf(" - Dispositivo en 0x%02X", addr);
if (addr >= 0x50 && addr <= 0x57) {
Serial.print(" (EEPROM candidata)");
if (!picked) { eepromAddr = addr; picked = true; }
}
Serial.println();
}
delay(2);
}
if (!any) Serial.println(" (Nada encontrado)");
if (picked) Serial.printf("Usando EEPROM en 0x%02Xn", eepromAddr);
else Serial.println("No se detectó EEPROM (0x50–0x57).");
}
// Verifica protección de escritura intentando cambiar y restaurar un byte
void cmdWPCheck(uint16_t memAddr) {
uint8_t orig = 0xFF, test;
if (!eepromReadSeq(memAddr, &orig, 1)) { Serial.println("Lectura inicial falló."); return; }
test = (orig == 0xFF) ? 0x00 : 0xFF; // valor diferente seguro
if (!eepromWritePaged(memAddr, &test, 1)) { // algunos chips con WP alto NACKean la escritura
Serial.println("Escritura NACK → posible WP ACTIVA o bus error.");
return;
}
uint8_t after = 0xFF;
if (!eepromReadSeq(memAddr, &after, 1)) { Serial.println("Lectura posterior falló."); return; }
if (after != test) {
Serial.printf("WP ACTIVA: Byte no cambió (0x%02X -> 0x%02X leído 0x%02X)n", orig, test, after);
return;
}
// Si sí cambió, WP está desactivada; restauramos el valor original.
if (!eepromWritePaged(memAddr, &orig, 1)) {
Serial.println("¡Atención! No se pudo restaurar el valor original.");
} else {
eepromReadSeq(memAddr, &after, 1);
}
Serial.printf("WP DESACTIVADA: se pudo escribir y restaurar (final=0x%02X)n", after);
}
void cmdRead(uint16_t addr, int len) {
if (len <= 0 || len > 256) { Serial.println("len max 256"); return; }
uint8_t buf[256];
if (eepromReadSeq(addr, buf, len)) {
Serial.println("HEX:"); dumpHex(buf, len);
Serial.print("ASCII: ");
for (int i = 0; i < len; i++) Serial.print((buf[i] >= 32 && buf[i] < 127) ? (char)buf[i] : '.');
Serial.println();
} else Serial.println("Error de lectura");
}
void cmdWrite(uint16_t addr, const String& text) {
if (eepromWritePaged(addr, (const uint8_t*)text.c_str(), text.length()))
Serial.printf("Escrito en 0x%04Xn", addr);
else
Serial.println("Error de escritura (WP alto, dirección o bus).");
}
void cmdErase() {
Serial.println("Borrando toda la EEPROM (0xFF)...");
const int total = 4096; // 32 Kbit = 4 KB
uint8_t ff[32]; memset(ff, 0xFF, sizeof(ff));
for (int a = 0; a < total; a += 32) {
if (!eepromWritePaged(a, ff, 32)) { Serial.printf("Fallo en 0x%04Xn", a); break; }
}
Serial.println("Borrado completo.");
}
// Permite fijar manualmente la dirección encontrada
void cmdAddrSet(uint8_t addr) {
eepromAddr = addr;
Serial.printf("Dirección EEPROM seleccionada: 0x%02Xn", eepromAddr);
}
// ---------- Parser ----------
String input;
void handleCommand(String line) {
line.trim();
if (line.length() == 0) return;
if (line == "scan") { cmdScan(); return; }
if (line.startsWith("addr ")) {
String s = line.substring(5);
uint8_t v = s.startsWith("0x") ? strtoul(s.c_str(), nullptr, 16) : (uint8_t)s.toInt();
cmdAddrSet(v); return;
}
if (line.startsWith("read ")) {
int sp1 = line.indexOf(' ');
int sp2 = line.indexOf(' ', sp1 + 1);
if (sp1 < 0 || sp2 < 0) { Serial.println("Uso: read <addr> <len>"); return; }
String a = line.substring(sp1 + 1, sp2), b = line.substring(sp2 + 1);
uint16_t addr = a.startsWith("0x") ? strtoul(a.c_str(), nullptr, 16) : (uint16_t)a.toInt();
int len = b.toInt();
cmdRead(addr, len); return;
}
if (line.startsWith("write ")) {
int sp1 = line.indexOf(' ');
int sp2 = line.indexOf(' ', sp1 + 1);
if (sp1 < 0 || sp2 < 0) { Serial.println("Uso: write <addr> <texto>"); return; }
String a = line.substring(sp1 + 1, sp2), text = line.substring(sp2 + 1);
uint16_t addr = a.startsWith("0x") ? strtoul(a.c_str(), nullptr, 16) : (uint16_t)a.toInt();
cmdWrite(addr, text); return;
}
if (line == "erase") { cmdErase(); return; }
if (line.startsWith("wpcheck")) {
// wpcheck [addr]
uint16_t m = 0x0000;
int sp = line.indexOf(' ');
if (sp > 0) {
String a = line.substring(sp + 1);
if (a.length()) m = a.startsWith("0x") ? strtoul(a.c_str(), nullptr, 16) : (uint16_t)a.toInt();
}
cmdWPCheck(m); return;
}
Serial.println("Comandos:");
Serial.println(" scan");
Serial.println(" addr <0x50..0x57>");
Serial.println(" read <addr> <len> (addr admite 0x..)");
Serial.println(" write <addr> <texto>");
Serial.println(" erase");
Serial.println(" wpcheck [addr] (prueba WP; por defecto 0x0000)");
}
void setup() {
Serial.begin(115200);
delay(200);
#if defined(ESP8266) || defined(ESP32)
Wire.begin(SDA_PIN, SCL_PIN);
#else
Wire.begin();
#endif
Wire.setClock(100000);
Serial.println("Monitor I2C-EEPROM listo. Escribe 'scan' para detectar la EEPROM.");
}
void loop() {
while (Serial.available()) {
char c = Serial.read();
if (c == 'n' || c == 'r') { if (input.length()) { handleCommand(input); input = ""; } }
else input += c;
}
}
Posteriormente a la escritura del código, en el monitor serial escribimos las siguientes funciones, teniendo como resultado lo siguiente:
| scan: Escanea dispositivos I2C y detecta la EEPROM Ejemplo: scanread: Lee datos desde una dirección de memoria Ejemplo: read 0x0000 16write: Escribe texto en una dirección de memoria Ejemplo: write 0x0000 Hola Mundoerase: Borra toda la EEPROM (la rellena con 0xFF) Ejemplo: erasewpcheck [addr]: Verifica el estado de protección contra escritura Ejemplo: wpcheck 0x0000addr: Establece manualmente la dirección I2C de la EEPROM Ejemplo: addr 0x50 |
![]() |





























Valoraciones
No hay valoraciones aún.