4. EEPROM与Flash的读写特性:擦写寿命、页写入与字节写入、磨损均衡策略

EEPROM和Flash,这两兄弟几乎撑起了单片机非易失存储的半边天。很多初学者觉得它们差不多——都能断电保存数据嘛。但实际用起来,脾气可差远了。我最早做产品时就在这上面栽过跟头,今天咱们把它们的读写特性掰开揉碎讲清楚。

4.1 擦写寿命:不是无限次随便写的

先说个扎心的事实:EEPROM和Flash都有寿命限制。不是写一次就坏,而是写到一定次数后,某个存储单元就“罢工”了。

存储器类型 典型擦写寿命 数据保持时间
EEPROM 10万 ~ 100万次 10 ~ 40年
NOR Flash 1万 ~ 10万次 10 ~ 20年
NAND Flash 3000 ~ 10万次 5 ~ 10年

你看,EEPROM的寿命明显比Flash长。但别高兴太早——EEPROM的容量通常只有几KB到几十KB,而Flash动不动就是几MB甚至上百MB。这就是鱼和熊掌的问题。

⚠️ 我曾经踩过的坑: 有个项目需要频繁记录设备运行日志,我图省事直接往Flash同一个地址写数据。结果不到三个月,那个扇区就报废了。后来一算,每天写几千次,1万次的寿命根本扛不住。所以,千万别把频繁变化的数据往固定地址写,尤其是Flash。

4.2 页写入与字节写入:速度与灵活性的博弈

EEPROM和Flash在写入方式上有个本质区别。EEPROM支持字节写入,而Flash只能页写入。什么意思呢?

  • EEPROM字节写入:想改哪个字节就改哪个字节,不需要先擦除。写入时间大约3~10ms/字节。
  • Flash页写入:必须先擦除整个扇区(通常256字节~4KB),然后再写入。擦除一次要几十到几百毫秒。

你想想看,如果我只想改一个字节的数据,用EEPROM直接写就行。但用Flash呢?得先把整个扇区读到RAM里,擦除扇区,修改那个字节,再把整个扇区写回去。这操作量完全不是一个级别。

💡 我的个人习惯: 保存配置参数、校准数据这类小量且需要频繁修改的数据,我优先用EEPROM。保存固件、字库、音频等大块数据,用Flash。各司其职,别混着用。

4.3 磨损均衡策略:让存储单元“雨露均沾”

既然每个存储单元都有寿命限制,那怎么让它们“活”得更久?答案就是磨损均衡——把写操作均匀分布到所有存储单元上,避免某些单元过度使用。

我做过一个智能电表项目,需要每5秒记录一次电压数据。如果直接写固定地址,Flash撑不过一周。后来用了磨损均衡,愣是让设备跑了5年没出问题。

4.3.1 基本思路:地址映射 + 日志结构

磨损均衡的核心思想很简单:不直接写固定地址,而是通过一个映射表,把逻辑地址映射到物理地址。每次写入时,找下一个可用的物理地址写,同时更新映射表。

// 简单的磨损均衡示例(伪代码)
uint16_t logical_to_physical[LOGICAL_PAGES];
uint16_t next_free_page = 0;

void wear_levelling_write(uint16_t logical_addr, uint8_t *data) {
    // 找到当前逻辑地址对应的物理地址
    uint16_t old_phys = logical_to_physical[logical_addr];
    
    // 标记旧页为无效
    mark_page_invalid(old_phys);
    
    // 找下一个空闲页
    uint16_t new_phys = find_next_free_page();
    
    // 写入数据
    flash_page_write(new_phys, data);
    
    // 更新映射表
    logical_to_physical[logical_addr] = new_phys;
}

说白了,就是让数据在存储空间里“流动”起来,而不是死磕一个地方。

4.3.2 三种常见策略对比

策略 原理 优点 缺点
日志结构 新数据追加写入,旧数据标记无效 实现简单,写入均匀 需要垃圾回收,读性能差
哈希映射 通过哈希函数将逻辑地址映射到物理地址 查找速度快 哈希冲突处理复杂
动态映射 运行时动态分配物理地址 灵活性高,磨损最均匀 需要RAM存储映射表

我个人比较推荐日志结构,尤其是在资源受限的单片机上。它不需要维护复杂的映射表,只需要一个写指针和一个无效标记位就行。

🔧 实用技巧: 磨损均衡的“均衡”不是绝对的。实际项目中,我会预留10%~20%的冗余空间作为“备用池”。当某个扇区寿命耗尽时,自动从备用池里拿一个替换。这样能显著延长整体寿命。

4.4 知识结构图:EEPROM与Flash读写特性全景

下面这张图把本章的核心知识点串起来了。你可以把它当作一个快速索引,遇到问题时回来瞄一眼。

EEPROM与Flash读写特性全景 非易失存储器 EEPROM Flash 字节写入 寿命:10万~100万次 无需先擦除 页写入 寿命:1万~10万次 必须先擦除再写 磨损均衡策略 日志结构 哈希映射 动态映射 核心原则:避免固定地址频繁写入,让写操作均匀分布到所有存储单元

4.5 实际项目中的选择建议

说了这么多,到底怎么选?我总结了几条实战经验:

  • 配置参数类数据(设备地址、校准系数等):用EEPROM。改得少,但每次改都要精确到字节。
  • 日志记录类数据(运行状态、故障记录等):用Flash + 磨损均衡。数据量大,写入频繁,必须做均衡。
  • 固件升级:用Flash。大块数据写入,页写入效率高。
  • 掉电保护场景:优先EEPROM。字节写入原子性强,掉电不容易丢数据。
📌 记住这个原则: 写频率越高,越要做磨损均衡。如果每天写超过100次,别犹豫,直接上均衡策略。否则,你的产品可能活不过保修期。