单片机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

相关推荐
CQ_YM9 小时前
ARM时钟与定时器
arm开发·单片机·嵌入式硬件·arm
xiebs_9 小时前
0127TR
单片机·嵌入式硬件
DLGXY14 小时前
STM32——EXTI外部中断(六)
stm32·单片机·嵌入式硬件
LEEE@FPGA14 小时前
zynq 是不是有了设备树,再linux中不需要编写驱动也能控制
linux·运维·单片机
同志啊为人民服务!14 小时前
RS485通信,无法进入中断处理程序,问题分析过程
单片机·编译器·rs485·中断处理程序
Hello_Embed16 小时前
Modbus 协议报文解析
笔记·stm32·单片机·学习·modbus
麒qiqi16 小时前
ADC 的原理与实战
c语言·开发语言·单片机·嵌入式硬件
WD1372980155718 小时前
30V降12V,8A大功率高集成同步降压IC,工业电源WD5030K
stm32·单片机·嵌入式硬件·电脑
愈心凌18 小时前
知识碎片——STM32的定时器时钟解读
stm32·单片机·嵌入式硬件
松涛和鸣19 小时前
DAY65 IMX6ULL: ADC Light Sensor Detection and LCD Display Driver
服务器·arm开发·单片机·嵌入式硬件·html