介绍
基于AT24C系列I²C EEPROM芯片的存储模块,常见型号AT24C02(2Kbit)/AT24C04(4Kbit)/AT24C08(8Kbit)/AT24C16(16Kbit)/AT24C32(32Kbit)/AT24C64(64Kbit)/AT24C256(256Kbit),I²C接口,电压1.8-5.5V,支持100万次擦写,数据保持100年,板载I²C上拉电阻和地址选择焊盘
基于AT24C系列I²C EEPROM芯片的存储模块,常见型号AT24C02(2Kbit)/AT24C04(4Kbit)/AT24C08(8Kbit)/AT24C16(16Kbit)/AT24C32(32Kbit)/AT24C64(64Kbit)/AT24C256(256Kbit),I²C接口,电压1.8-5.5V,支持100万次擦写,数据保持100年,板载I²C上拉电阻和地址选择焊盘
| 参数 | 值 |
|---|---|
| 接口 | I²C (TWI) |
| I²C地址 | 0x50~0x57(由A0/A1/A2引脚决定,AT24C16以下部分地址位用于页选择) |
| 工作电压 | 1.8V ~ 5.5V |
| 擦写次数 | 100万次 |
| 数据保持 | 100年 |
| 最大时钟 | 400kHz (Fast Mode) |
| 板载特性 | I²C上拉电阻、地址选择焊盘、写保护跳线 |
| 模块尺寸 | 约 18x14mm |
| 芯片系列 | AT24C02/04/08/16/32/64/256 |
| 页写大小 | 8/16/32/64字节(视型号) |
# AT24Cxx EEPROM 存储模块 — 代码例程
---
## 示例 1:Arduino — 使用 Wire 库读写单字节
```cpp
/*
* AT24Cxx EEPROM — Arduino Wire库 单字节读写
* 接线: SCL→A5, SDA→A4 (Uno/Nano), VCC→5V, GND→GND
* 地址默认 0x50 (A0=A1=A2=GND)
*/
#include <Wire.h>
#define EEPROM_ADDR 0x50 // 7位地址
void eepromWriteByte(uint16_t addr, uint8_t data) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write((addr >> 8) & 0xFF); // 高字节地址
Wire.write(addr & 0xFF); // 低字节地址
Wire.write(data);
Wire.endTransmission();
delay(10); // 等待写周期
}
uint8_t eepromReadByte(uint16_t addr) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write((addr >> 8) & 0xFF);
Wire.write(addr & 0xFF);
Wire.endTransmission();
Wire.requestFrom(EEPROM_ADDR, (uint8_t)1);
if (Wire.available()) {
return Wire.read();
}
return 0xFF;
}
void setup() {
Wire.begin();
Serial.begin(115200);
Serial.println("AT24Cxx EEPROM 测试");
// 写一个字节
eepromWriteByte(0x00, 0xAB);
Serial.println("写入: 0xAB → 地址 0x00");
// 读回
uint8_t val = eepromReadByte(0x00);
Serial.print("读出: 0x");
Serial.println(val, HEX);
}
void loop() { }
```
---
## 示例 2:Arduino — 页写入 + 任意长度读写
```cpp
/*
* AT24Cxx EEPROM — 页写入 & 批量读写
* 适用于 AT24C02(8字节页) ~ AT24C256(64字节页)
*/
#include <Wire.h>
#define EEPROM_ADDR 0x50
// 根据芯片型号定义页大小
// AT24C02/04/08/16: 16, AT24C32/64: 32, AT24C256: 64
#define PAGE_SIZE 32 // AT24C64 为例
void eepromPageWrite(uint16_t addr, const uint8_t *data, uint8_t len) {
if (len > PAGE_SIZE) len = PAGE_SIZE;
// 确保不跨页边界
uint8_t spaceInPage = PAGE_SIZE - (addr % PAGE_SIZE);
if (len > spaceInPage) len = spaceInPage;
Wire.beginTransmission(EEPROM_ADDR);
Wire.write((addr >> 8) & 0xFF);
Wire.write(addr & 0xFF);
for (uint8_t i = 0; i < len; i++) {
Wire.write(data[i]);
}
Wire.endTransmission();
delay(10);
}
void eepromRead(uint16_t addr, uint8_t *buf, uint8_t len) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write((addr >> 8) & 0xFF);
Wire.write(addr & 0xFF);
Wire.endTransmission();
Wire.requestFrom(EEPROM_ADDR, len);
uint8_t i = 0;
while (Wire.available() && i < len) {
buf[i++] = Wire.read();
}
}
void setup() {
Wire.begin();
Serial.begin(115200);
// 写入字符串
const char *msg = "Hello EEPROM!";
eepromPageWrite(0x00, (const uint8_t*)msg, strlen(msg));
Serial.print("写入: ");
Serial.println(msg);
// 读回
char buf[32] = {0};
eepromRead(0x00, (uint8_t*)buf, strlen(msg));
Serial.print("读回: ");
Serial.println(buf);
}
void loop() { }
```
---
## 示例 3:Arduino — 存储/读取配置结构体
```cpp
/*
* AT24Cxx — 存储配置结构体(含校验和)
*/
#include <Wire.h>
#define EEPROM_ADDR 0x50
struct Config {
uint8_t deviceId;
uint16_t baudRate;
float calibFactor;
uint8_t checksum;
};
uint8_t calcChecksum(uint8_t *data, uint8_t len) {
uint8_t sum = 0;
for (uint8_t i = 0; i < len - 1; i++) sum ^= data[i];
return sum;
}
void saveConfig(Config &cfg) {
cfg.checksum = calcChecksum((uint8_t*)&cfg, sizeof(Config));
Wire.beginTransmission(EEPROM_ADDR);
Wire.write(0x00); Wire.write(0x00); // 起始地址 0
Wire.write((uint8_t*)&cfg, sizeof(Config));
Wire.endTransmission();
delay(10);
Serial.println("配置已保存");
}
bool loadConfig(Config &cfg) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write(0x00); Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(EEPROM_ADDR, sizeof(Config));
if (Wire.available() == sizeof(Config)) {
Wire.readBytes((uint8_t*)&cfg, sizeof(Config));
uint8_t ck = calcChecksum((uint8_t*)&cfg, sizeof(Config));
if (ck == cfg.checksum) {
Serial.println("配置加载成功(校验通过)");
return true;
}
}
Serial.println("配置无效,使用默认值");
return false;
}
void setup() {
Wire.begin();
Serial.begin(115200);
Config myConfig = {1, 115200, 1.05f, 0};
saveConfig(myConfig);
Config loaded;
if (loadConfig(loaded)) {
Serial.print("ID:"); Serial.println(loaded.deviceId);
Serial.print("Baud:"); Serial.println(loaded.baudRate);
Serial.print("Calib:"); Serial.println(loaded.calibFactor, 2);
}
}
void loop() { }
```
---
## 示例 4:STM32 HAL — I²C 驱动 AT24Cxx
```c
/*
* STM32 HAL — I2C1 读写 AT24Cxx
* CubeMX: 使能 I2C1,标准模式 100kHz 或 Fast 400kHz
*/
#include "main.h"
#define EEPROM_ADDR (0x50 << 1) // HAL 用8位地址
I2C_HandleTypeDef hi2c1;
HAL_StatusTypeDef EEPROM_WriteByte(uint16_t addr, uint8_t data) {
uint8_t buf[3] = {(addr >> 8) & 0xFF, addr & 0xFF, data};
HAL_StatusTypeDef ret = HAL_I2C_Master_Transmit(
&hi2c1, EEPROM_ADDR, buf, 3, 100
);
HAL_Delay(10); // 等待内部写周期
return ret;
}
HAL_StatusTypeDef EEPROM_ReadByte(uint16_t addr, uint8_t *data) {
uint8_t addrBuf[2] = {(addr >> 8) & 0xFF, addr & 0xFF};
// 先发地址
HAL_I2C_Master_Transmit(&hi2c1, EEPROM_ADDR, addrBuf, 2, 100);
// 再读数据
return HAL_I2C_Master_Receive(&hi2c1, EEPROM_ADDR, data, 1, 100);
}
// 页写入(不跨页)
HAL_StatusTypeDef EEPROM_PageWrite(uint16_t addr, uint8_t *data, uint8_t len) {
uint8_t buf[66]; // 最大64字节数据 + 2字节地址
buf[0] = (addr >> 8) & 0xFF;
buf[1] = addr & 0xFF;
memcpy(buf + 2, data, len);
HAL_StatusTypeDef ret = HAL_I2C_Master_Transmit(
&hi2c1, EEPROM_ADDR, buf, len + 2, 200
);
HAL_Delay(10);
return ret;
}
```
---
## 示例 5:MicroPython (ESP32 / Raspberry Pi Pico)
```python
"""
AT24Cxx EEPROM — MicroPython I2C 驱动
ESP32: SCL→GPIO22, SDA→GPIO21
"""
from machine import I2C, Pin
import time
class AT24Cxx:
def __init__(self, i2c, addr=0x50, page_size=32):
self.i2c = i2c
self.addr = addr
self.page_size = page_size
def write_byte(self, mem_addr, data):
buf = bytearray([(mem_addr >> 8) & 0xFF, mem_addr & 0xFF, data])
self.i2c.writeto(self.addr, buf)
time.sleep_ms(10) # 等待写周期
def read_byte(self, mem_addr):
buf = bytearray([(mem_addr >> 8) & 0xFF, mem_addr & 0xFF])
self.i2c.writeto(self.addr, buf)
return self.i2c.readfrom(self.addr, 1)[0]
def write_page(self, mem_addr, data):
"""写入不超过一页的数据"""
space = self.page_size - (mem_addr % self.page_size)
chunk = data[:min(len(data), space)]
buf = bytearray(2 + len(chunk))
buf[0] = (mem_addr >> 8) & 0xFF
buf[1] = mem_addr & 0xFF
buf[2:] = chunk
self.i2c.writeto(self.addr, buf)
time.sleep_ms(10)
def read(self, mem_addr, length):
buf = bytearray([(mem_addr >> 8) & 0xFF, mem_addr & 0xFF])
self.i2c.writeto(self.addr, buf)
return self.i2c.readfrom(self.addr, length)
# 使用示例
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
eeprom = AT24Cxx(i2c, addr=0x50, page_size=32)
# 写入
eeprom.write_byte(0x00, 0xDE)
print(f"写入字节: 0xDE")
# 读取
val = eeprom.read_byte(0x00)
print(f"读回: {hex(val)}")
# 写入字符串
msg = b"MicroPython EEPROM"
eeprom.write_page(0x10, msg)
data = eeprom.read(0x10, len(msg))
print(f"字符串读回: {data.decode()}")
```
暂无参考文献