This chat conversation is shared from TypingMind.com
Avatar of the person chatting

在 ESP32 芯片下,用 Arduino 框架,对于 Pin21(SDA)和Pin22(SCL)的IIC上挂着不同地址的设备,写一个程序遍历IIC上所有地址的响应情况,并打印出设备地址

以下是使用Arduino框架在ESP32上编写的一个简单程序,该程序会遍历所有可能的I2C地址,并检查哪些地址上有设备响应。在此程序中,我们使用默认的I2C引脚21(SDA)和22(SCL)。

#include <Wire.h>

void setup() {
  Wire.begin(21, 22); // 初始化I2C总线,SDA为21号引脚,SCL为22号引脚
  Serial.begin(115200); // 初始化串口通信,波特率为115200
  while (!Serial); // 等待串口连接
  Serial.println("\nI2C Scanner");
}

void loop() {
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.print(address, HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error == 4) {
      Serial.print("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000); // 等待5秒后再次扫描
}

在这个程序中,Wire.begin(21, 22); 调用初始化了ESP32的I2C总线,使用引脚21作为SDA(数据线)和引脚22作为SCL(时钟线)。Wire.beginTransmission(address); 开始向某个地址发送数据,而 Wire.endTransmission(); 结束传输并返回状态。如果返回值是0,表示设备已经响应了这个地址。程序会遍历从1到126的所有可能的7位I2C地址(8位地址的最高位是方向位,因此实际上只有7位用于寻址,地址范围0x01到0x7E),并打印出响应的设备地址。

请注意,有些设备可能使用保留地址或可能不响应广播扫描。另外,确保你的ESP32板子的核心库是最新的,以便支持所有功能和修复。

在上传并运行此代码之后,打开Arduino IDE的串口监视器,你应该能看到程序打印出找到的所有设备的I2C地址。

Avatar of the person chatting

初始化运行后,串口打印如下错误日志“[W][esp32-hal-i2c.c:1419] i2cCheckLineState(): invalid state sda(21)=1, scl(22)=0 [D][esp32-hal-i2c.c:1427] i2cCheckLineState(): Recovered after 1 Cycles [E][esp32-hal-i2c.c:1434] i2cCheckL”

该错误日志表明ESP32在尝试初始化I2C总线时遇到了问题。错误信息提示SDA(21号引脚)和SCL(22号引脚)之间的线路状态无效。此外,日志信息被截断了,但根据给出的部分,我们可以看到I2C驱动程序试图恢复总线状态但似乎失败了。

这个问题可能是由几个原因造成的:

  1. 硬件连接问题:确保SDA和SCL引脚上连接了正确的上拉电阻。通常,I2C总线上的SDA和SCL线需要连接到3.3V电源线上的上拉电阻,电阻值通常在4.7kΩ至10kΩ之间。没有正确的上拉电阻,I2C总线可能无法正常工作。

  2. 引脚冲突:确保引脚21和22没有被其他设备或板上的其他功能占用。

  3. 设备冲突:如果I2C总线上挂载了不兼容的设备或设备之间存在地址冲突,也可能导致这样的问题。确保所有连接的设备都正确配置了不同的I2C地址。

  4. I2C速率问题:在某些情况下,I2C通信速率设置过高可能导致通信故障。尝试降低I2C速率,查看是否解决了问题。

你可以尝试以下几种解决方法:

  • 检查硬件连接,特别是SDA和SCL引脚是否有正确的上拉电阻。
  • 如果你使用的是自制或非标准的I2C设备,请检查其硬件设计是否符合I2C规范。
  • 重新启动ESP32,有时硬件可能需要重置才能正确初始化。
  • 尝试使用不同的I2C引脚(如果你的ESP32开发板允许)。
  • 降低I2C通信速率,通过Wire.setClock(100000L);设置为标准的100kHz速率,或者更低。
  • 如果这些方法都不起作用,考虑检查ESP32开发板是否有损坏,或者尝试使用其他开发板。

你可以在setup()函数中添加Wire.setClock(100000L);来降低I2C速率,如下所示:

void setup() {
  Wire.begin(21, 22); // 初始化I2C总线,SDA为21号引脚,SCL为22号引脚
  Wire.setClock(100000L); // 设置I2C时钟速率为100kHz
  Serial.begin(115200); // 初始化串口通信,波特率为115200
  while (!Serial); // 等待串口连接
  Serial.println("\nI2C Scanner");
}

请按照以上建议进行检查和调整,然后重新运行I2C扫描程序。