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

ESP32 Arduino中I2C通信数据顺序异常问题排查

ESP32 I2C从机响应值偏移问题修复

问题现象

使用Arduino IDE(板卡管理器v2.0.17)将ESP32配置为I2C从机,实现「主机发送数据,从机返回该数据两倍值」的测试时,出现响应顺序异常:

  • 主机发送1,收到10(对应上一轮测试中5的两倍值)
  • 后续发送2收到2、发送3收到4,以此类推,响应值整体偏移一次

从机串口输出显示数据处理逻辑正常,仅主机接收顺序异常。

核心原因

  1. 内存残留问题:ESP32重启后,全局变量responseValue可能保留上一次运行的残留值(如测试最后处理的是5,responseValue为10),导致第一次请求返回旧值。
  2. I2C接收缓冲区未清空:receiveEvent中仅读取1字节,未处理完所有接收数据,若存在残留会干扰后续逻辑。

修复代码

从机代码(关键优化)

#include <Wire.h>

int receivedValue = 0;
int responseValue = 0xFF; // 用0xFF作为未初始化的标识值,避免残留干扰

void setup() {
  Wire.begin(0x08); // 加入I2C总线,地址0x08
  Wire.onReceive(receiveEvent); // 注册接收事件
  Wire.onRequest(requestEvent); // 注册请求响应事件
  Serial.begin(115200);
}

void loop() {}

// 主机发送数据时触发
void receiveEvent(int howMany) {
  // 循环清空接收缓冲区,确保读取所有数据
  while (Wire.available()) {
    receivedValue = Wire.read();
  }
  responseValue = receivedValue * 2;
  Serial.print("Received from master: ");
  Serial.print(receivedValue);
  Serial.print(", Prepared to send: ");
  Serial.println(responseValue);
}

// 主机请求数据时触发
void requestEvent() {
  Wire.write(responseValue); // 返回计算后的两倍值
}

主机代码(可选优化)

#include <Wire.h>

const int slaveAddress = 0x08;

void setup() {
  Wire.begin(); // 作为主机加入I2C总线
  Serial.begin(115200);
}

void loop() {
  // 依次发送1-5
  for (int valueToSend = 1; valueToSend <= 5; valueToSend++) {
    sendAndReceive(valueToSend);
    delay(1000);
  }
}

void sendAndReceive(int valueToSend) {
  // 发送数据到从机
  Wire.beginTransmission(slaveAddress);
  Wire.write(valueToSend);
  int status = Wire.endTransmission();
  if (status != 0) {
    Serial.print("发送失败,错误码: ");
    Serial.println(status);
    return;
  }

  delay(100); // 无需过长延迟,中断处理可立即完成

  // 请求1字节响应
  Wire.requestFrom(slaveAddress, 1);
  
  if (Wire.available()) {
    int receivedValue = Wire.read();
    // 跳过第一次的初始无效响应(0xFF)
    if (valueToSend == 1 && receivedValue == 0xFF) {
      Serial.println("从机初始响应,跳过本次读取");
      return;
    }
    Serial.print("发送: ");
    Serial.print(valueToSend);
    Serial.print(", 接收: ");
    Serial.println(receivedValue);
  } else {
    Serial.println("未收到从机响应");
  }
}

验证结果

优化后主机串口输出将恢复正常:

发送: 1, 接收: 2
发送: 2, 接收: 4
发送: 3, 接收: 6
发送: 4, 接收: 8
发送: 5, 接收: 10

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 03:15:55