EEPROM模块踩坑

EEPROM 模块踩坑


坑 1:AT24C02 写入后等待延时不足导致数据丢失

第十三届国赛 · 发现者:左岚

现象

参数掉电后丢失,或连续写入时第二次写操作被静默忽略,但 I2C 时序和代码逻辑看起来正常。

原因

AT24C02 页写时序要求 Stop 信号后至少等待 5ms 才能发起下一次 I2C 操作。等待延时被削减后,芯片仍处于内部擦写周期中,后续操作会被忽略:

// 错误写法:只有 4 次 Delay,总等待约 1~2ms,不足 5ms
I2CStop();
I2C_Delay(255);
I2C_Delay(255);
I2C_Delay(255);
I2C_Delay(255);
// 后续 6 次被注释掉了

解决方法

恢复足够的等待次数,确保 Stop 后总延时 ≥ 5ms:

// 正确写法:共 10 次,保证写周期等待充足
I2CStop();
I2C_Delay(255); I2C_Delay(255); I2C_Delay(255); I2C_Delay(255); I2C_Delay(255);
I2C_Delay(255); I2C_Delay(255); I2C_Delay(255); I2C_Delay(255); I2C_Delay(255);

举一反三

  • AT24C02 写周期(tWR)典型值 5ms,最长 10ms,必须严格保证
  • 调试时不要随意注释"看起来多余"的延时,写周期等待是协议必须项
  • 进阶做法:用 ACK 轮询代替固定延时(收到 ACK 即说明写周期完成,更可靠)

坑 2:I2C 接收函数局部变量未初始化导致数据最高位污染

第十三届国赛 · 发现者:左岚

现象

I2C 数据接收偶发错误,接收到的字节最高位可能被随机污染,复位后偶尔恢复正常。

原因

I2CReceiveByte 中局部变量 da 未初始化,第一轮循环执行 da <<= 1da 含栈上垃圾值,最终结果的高位可能错误:

// 错误写法:da 未初始化,高位可能含垃圾值
unsigned char da;

解决方法

声明时显式初始化为 0:

// 正确写法
unsigned char da = 0;

举一反三

  • C51 局部变量存放于寄存器或栈,不自动清零,必须显式初始化
  • 所有参与移位、位或运算的变量,初值必须确定,否则结果不可预测
  • 养成声明时同步初始化的习惯,可彻底避免此类隐患