You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行时I2C超时但调试单步执行正常的AT24C32N问题求助

I2C起始条件超时问题:函数调用时失败,单步调试内部执行正常

问题描述

我正在开发基于I2C总线与AT24C32N EEPROM交互的代码,自行实现了I2C库,其中eeprom_write_data函数如下:

uint8_t eeprom_write_data(uint8_t *inputString[16])
{
   uint16_t eeAddr = 0;
   uint8_t err = 0;
   eeAddr = next_unused_addr(); // 读取0xFFF地址获取EEPROM中已存储的输入数量
   if(eeAddr == TWI_ERROR_START || eeAddr == TWI_ERROR_RSTART)
   {
      return eeAddr;
   }
   err = EEPROM_write_handler(eeAddr, inputString, sizeof(inputString)/sizeof(inputString[0])); // 写入数据到EEPROM
   if(err == TWI_OK)
   {
      err = increment_eeprom_counter(eeAddr); // 更新0xFFF地址处的输入计数
   }
   return err;
}

核心问题:调用increment_eeprom_counter(甚至替换成已验证可用的EEPROM_write_handler)时,I2C发送起始条件会超时。但单步进入函数内部逐行执行一切正常,直接单步跳过函数调用则触发超时。

排查方向与解决方案

1. 补全EEPROM写周期等待

AT24C32N完成一页写入后需要至少5ms的写周期时间,如果连续发起I2C操作时总线还处于忙状态,就会导致起始条件超时。

  • 确认EEPROM_write_handler返回TWI_OK时,是否等待了EEPROM的写完成?很多I2C库不会自动处理这个等待逻辑,需要手动在写操作后加入5ms左右的延时,再执行下一次I2C操作。
  • 单步调试时的时间间隔刚好满足了写周期要求,所以不会出问题;全速执行时两次操作间隔太短,触发超时。

2. 复位I2C外设状态寄存器

连续I2C操作后,硬件寄存器可能残留错误标志(比如未应答、仲裁丢失),导致新的起始条件无法正常发起:

  • 在increment_eeprom_counter执行前,检查并清除I2C(TWI)外设的错误状态位,必要时重新初始化I2C外设,确保总线处于空闲状态。

3. 修正参数长度计算错误

eeprom_write_data的参数uint8_t *inputString[16]是指针数组,sizeof(inputString)/sizeof(inputString[0])得到的是固定的16,但如果实际传入的是单个字符串指针,这个长度计算会导致EEPROM_write_handler写入超出预期的数据,破坏EEPROM状态进而影响后续操作:

  • 建议修改参数为uint8_t *inputString,并单独传入实际数据长度,避免依赖sizeof计算长度。

4. 排查栈溢出或内存异常

函数调用时的栈操作可能引发内存异常,间接影响I2C外设的配置:

  • 检查increment_eeprom_counter函数的栈使用情况,是否存在局部变量过多、递归调用等导致栈溢出的情况。
  • 确认编译器的栈大小配置,确保栈空间足够支撑函数调用。

5. 调整编译器优化级别

部分编译器优化级别(如-O2)可能会改变代码执行顺序,或优化掉必要的延时/寄存器操作:

  • 尝试降低优化级别至-O0,看问题是否消失。如果消失,再逐步排查被优化的代码部分,必要时用volatile关键字标记I2C相关的寄存器或变量,避免被编译器优化。

内容的提问来源于stack exchange,提问作者David Hala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:42:37