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 <<= 1 前 da 含栈上垃圾值,最终结果的高位可能错误:
// 错误写法:da 未初始化,高位可能含垃圾值
unsigned char da;
解决方法
声明时显式初始化为 0:
// 正确写法
unsigned char da = 0;
举一反三
- C51 局部变量存放于寄存器或栈,不自动清零,必须显式初始化
- 所有参与移位、位或运算的变量,初值必须确定,否则结果不可预测
- 养成声明时同步初始化的习惯,可彻底避免此类隐患