单片机EEPROM写入数据之前为什么要先擦除?

1. 物理原理:浮栅晶体管

EEPROM(和Flash)的基本存储单元是浮栅晶体管

text

复制代码
控制栅(CG) ──┐
              │
             ┌▼┐
            ┌┴─┴┐
            │氧化│← 浮栅(FG) - 存储电子
            └┬─┬┘
              │
             ┌▼┐  漏极(D)
源极(S) ─────►│ │◄──────
             └─┘

三种状态操作:

操作 原理 电子流向
擦除(Erase) 高电压到源极 电子流出 浮栅 → 逻辑1
写入(Program) 高电压到控制栅 电子注入 浮栅 → 逻辑0
读取(Read) 正常电压 检测浮栅是否有电子

2. 为什么必须先擦除?

2.1 物理限制:只能从1变0,不能从0变1

c

复制代码
// 物理上的位操作:
位状态 = 1  // 擦除后:浮栅无电子
位状态 = 0  // 写入后:浮栅有电子

// 关键限制:
// 0 → 1 ?  不可能!无法单独移除电子
// 只有擦除操作能批量移除电子(1 ← 0)

2.2 电路原理:

  • 写入(0):给控制栅加高压,电子通过隧道效应注入浮栅

  • 擦除(1):给源极加高压,电子通过隧道效应流出浮栅

  • 不能部分擦除:高压是施加到整个扇区的,无法选择单个位

3. 实际操作示例

情况1:新写入数据(正确流程)

c

复制代码
// 初始状态:扇区已擦除,所有位=0xFF (11111111b)
// 地址0x08E00000: 0xFF 0xFF 0xFF 0xFF ...

// 1. 先擦除(必须!)
擦除扇区();  // 所有位变为1

// 2. 写入数据
写入(0x08E00000, 0x55);  // 01010101b
// 物理过程:1→0(允许),0→1(不允许但不需要)
// 结果:0x55 写入成功

情况2:不擦除直接写入(会出错)

c

复制代码
// 假设当前内容:0xAA (10101010b)
// 目标写入:0x55 (01010101b)

// 错误做法:不擦除直接写
写入(0x08E00000, 0x55);

// 物理结果:
// 原来是0的位(1→0) → 保持0 ✓
// 原来是1的位(0→1) → 无法变为1! ✗
// 最终结果:0x00 (00000000b) 而不是0x55!

位级演示

text

复制代码
原始: 1 0 1 0 1 0 1 0  (0xAA)
写入: 0 1 0 1 0 1 0 1  (0x55)
结果: 0 0 0 0 0 0 0 0  (0x00) ← 错误!

4. 赛元SC32F12TK7的具体实现

4.1 最小擦除单位:扇区

SC32F12TK7的EEPROM结构:

  • 扇区大小:1KB (1024字节)

  • 擦除粒度整个扇区一起擦除

  • 写入粒度:可以单字节写入

4.2 完整写入流程

c

复制代码
// 需求:修改EEPROM中第10个字节(从0x08E00009)

// 步骤1:读取整个扇区到RAM缓存
uint8_t sector_buffer[1024];
memcpy(sector_buffer, (void*)0x08E00000, 1024);

// 步骤2:在RAM中修改数据
sector_buffer[9] = 新数据;  // 修改第10字节

// 步骤3:擦除整个扇区
擦除扇区(0x69000000);

// 步骤4:将整个缓冲区写回
for(int i = 0; i < 1024; i++) {
    写入(0x08E00000 + i, sector_buffer[i]);
}

5. 为什么设计成这样?(工程考量)

优点:

  1. 高密度:一个晶体管存1位,成本低

  2. 非易失:断电数据保存10年以上

  3. 可擦写:通常10万次以上(EEPROM)

缺点(必须接受的):

  1. 不能位寻址:只能批量擦除

  2. 速度慢:擦除需要几毫秒

  3. 寿命有限:擦写次数限制

6. 与其他存储器的对比

存储器类型 擦除需求 擦除单位 特点
EEPROM 必须 扇区(1KB) 字节写入,寿命长
Flash 必须 页/块(4KB+) 速度快,密度高
FRAM 不需要 无限次擦写,速度快
EEPROM模拟 需要 Flash块 用Flash模拟EEPROM

7. 最佳实践建议

7.1 数据管理策略

c

复制代码
// 方案1:日志式存储(避免频繁擦除)
struct {
    uint16_t index;  // 递增索引
    uint8_t data[32]; // 实际数据
} log_entry;

// 每次写入新日志,索引递增
// 扇区满后才擦除

// 方案2:数据轮换
uint8_t active_sector = 0;  // 当前活动扇区
// 一个扇区写满后切换到下一个

7.2 减少擦除次数的技巧

  1. 批量写入:收集足够数据后一次性写入

  2. 数据压缩:减少存储空间需求

  3. 使用RAM缓存:频繁修改的数据先放RAM

  4. 磨损均衡:轮流使用不同扇区

8.写之前的擦除要遵循的原则:

扇区擦除的原则,以3个扇区每个扇区512个字节,每次写入32个字节(子扇区32个字节)为例:

①要保证当前写的是空的子扇区。( 这一条可以删除,跟下面一条找有效地址相辅相成,如果找到了有效地址说明要写的区域就是空的)。

②要保证有空的地址区域(子扇区)便于上电恢复时"找有效地址函数"能找到要写有效地址(就是能找到空地址(空的子扇区)进行写操作,可以在每次写的时候执行判断决定是否执行擦除操作,确保下一次要写的区域是空的)。

保证了这一条其实就保证了第①条写入的区域是经过擦除的区域( 如果找到了有效地址说明要写的区域就是空的**,默认第一次写之前所有扇区是空的擦除过的(配置字设置))。**

可以每次写的时候:

如果要写的是扇区起始子扇区,擦除当前整个扇区

如果要写的是扇区最后一个子扇区,擦除下一个扇区

注:通常要配合配置字来控制,也就是第一次上电里面都是空的,有些找有效地址函数前提是没写过的时候是空的(擦除状态).

9. 常见错误及避免

c

复制代码
// ❌ 错误:局部更新不擦除
*(uint8_t*)0x08E00000 = 0x11;  // 第一次:OK
*(uint8_t*)0x08E00000 = 0x22;  // 第二次:失败!需要先擦除

// ✅ 正确:读写-修改-写回
// 1. 读整个扇区到RAM
// 2. 在RAM中修改
// 3. 擦除扇区
// 4. 写回整个扇区

总结:

  1. 物理限制:浮栅晶体管只能从1→0,不能0→1

  2. 擦除是唯一将0变1的方法:通过高压移除电子

  3. 最小擦除单位是扇区:无法单独擦除某个字节

  4. 必须按"读取-修改-擦除-写入"流程操作

  5. 设计应用时要考虑EEPROM特性:减少擦写次数,延长寿命

这种"先擦后写"的特性是所有基于浮栅晶体管的非易失存储器的共同特点,理解这一点对嵌入式存储设计至关重要。

以上部分内容总结自deepseek

相关推荐
tianyue1005 小时前
STM32G431 ADC 多个channel 采集
stm32·单片机·嵌入式硬件
清风6666666 小时前
基于单片机的水泵效率温差法测量与报警系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
z20348315208 小时前
定时器练习报告
单片机·嵌入式硬件
zk008 小时前
内容分类目录
单片机·嵌入式硬件
安生生申8 小时前
STM32 ESP8266连接ONENET
c语言·stm32·单片机·嵌入式硬件·esp8266
广药门徒8 小时前
电子器件烧毁的底层逻辑与避坑指南
单片机·嵌入式硬件
点灯小铭13 小时前
基于单片机的社区医院小型高压蒸汽灭菌自动控制器设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
youcans_13 小时前
【动手学STM32G4】(3)STM32G431之定时器
stm32·单片机·嵌入式硬件·定时器
悠哉悠哉愿意13 小时前
【嵌入式学习笔记】AD/DA
笔记·单片机·嵌入式硬件·学习
松涛和鸣13 小时前
DAY47 FrameBuffer
c语言·数据库·单片机·sqlite·html