AT24Cxx EEPROM 存储模块 — 代码例程
示例 1:Arduino — 使用 Wire 库读写单字节
#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 — 页写入 + 任意长度读写
#include <Wire.h>
#define EEPROM_ADDR 0x50
#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 — 存储/读取配置结构体
#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
#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)
"""
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()}")