4
\$\begingroup\$

When setting up I2C communications, I know that it is certainly ideal to have the devices' datasheet(s), and find the I2C address of the device(s) that way. However, in some reverse-engineering applications, you don't have a datasheet available. (Or, you may just not be able to find it...)

Without the datasheet, how do you determine the default I2C address of a device? Also, what tool(s)/equipment do you need? (e.g. is a microcontroller with I2C support enough, or do you need an oscilloscope?)

\$\endgroup\$
  • 1
    \$\begingroup\$ Same way as finding the IP address of an arbitrary host: The hard way. \$\endgroup\$ – Ignacio Vazquez-Abrams Jul 21 '13 at 19:09
  • \$\begingroup\$ Are you trying to do this once to then write it down, or determine i2c addresses for new devices every time the device powers on? \$\endgroup\$ – crasic Jul 21 '13 at 19:11
  • 1
    \$\begingroup\$ The address is only a tiny bit of an i2c device. Without a datasheet, how will you know what commands to send? \$\endgroup\$ – Passerby Jul 21 '13 at 19:24
  • 2
    \$\begingroup\$ The Bus Pirate has a command ("1") for searching I2C addresses: dangerousprototypes.com/bus-pirate-manual/i2c-guide \$\endgroup\$ – starblue Jul 22 '13 at 7:44
  • 1
    \$\begingroup\$ @Passerby Getting the addresses can help you figure out what devices are present by type, after which a datasheet search can be more fruitful. (I'm assuming OP isn't able to determine by physical inspection what devices are present on the bus.) \$\endgroup\$ – Adam Lawrence Jul 22 '13 at 12:54
11
\$\begingroup\$

It's fairly easy to write an I2C "ping" utility for a microcontroller. All you need to do is scan through the ~128 addresses and for each one:

  1. Send I2C Start condition
  2. Send a single byte representing the address, and get the ACK/NAK
  3. Send the stop condition.

If there is an ACK (the data line held low on the 9th clock cycle) then a device with that address is present on the I2C bus. If there is no ACK then no device is present.

Don't forget that I2C addresses are in the upper 7 bits of the byte (the last bit is for read/write). Also, don't forget to ignore the special I2C addresses in your scan: http://www.i2c-bus.org/addressing/

As for hardware almost anything will work. Even if your device doesn't have I2C support it's a simple enough (and slow enough) protocol where you can bit bang it. Just make sure that whatever you use never drives the I2C lines high, only low (as per spec).

\$\endgroup\$
  • \$\begingroup\$ Just a side note, knowing what the i2c device does would also help. For example, i2c Eeproms can ack multiple addresses. \$\endgroup\$ – Passerby Jul 21 '13 at 19:22
  • \$\begingroup\$ @Passerby Good point. Many I2C devices have at least one hardware selectable address bit, and some such as EEPROMs have more. The EEPROMs that I have worked with have 4. With any sort of hardware scan you'll only be able to get the currently set address, not all possible addresses for that device. \$\endgroup\$ – srlm Jul 21 '13 at 19:46
  • 2
    \$\begingroup\$ Well, yes, that too, but bigger i2c eeproms work like multiple smaller i2c eeproms, with the same address. A 4kb eeprom responds to only one address, but a 32kb eeprom responds to multiple addresses, including the same address that the 4kb eeprom would, because the page is part of the address. \$\endgroup\$ – Passerby Jul 21 '13 at 19:58
9
\$\begingroup\$

If you don't want to do it manually:

  • Hook up a Raspberry Pi
  • Run sudo i2cdetect -y 0
  • If Run sudo i2cdetect -y 0 does not work, Run sudo i2cdetect -y 1
\$\endgroup\$
  • \$\begingroup\$ Wow. This just solved my problem. Thank you. \$\endgroup\$ – Sudarshan Kadam Aug 20 '19 at 4:57
2
\$\begingroup\$

Here's a snippet of Arduino code that I use:

for (int address=1; address <= 126; address++) {
  Wire.beginTransmission(address); // Select address
  if (!Wire.endTransmission()) Serial.printf("Found device at: %02Xh\n", address); 
}
\$\endgroup\$
1
\$\begingroup\$

You can connect SCL/SDA to an Arduino board, power the I2C device up then run on the Arduino board this code:

// i2c_scanner
 //
 // This program (or code that looks like it)
 // can be found in many places.
 // For example on the Arduino.cc forum.
 // The original author is not know.
 //
 // This sketch tests the standard 7-bit addresses
 // from 0 to 127. Devices with higher bit address
 // might not be seen properly.
 //
 // Adapted to be as simple as possible by Arduino.cc user Krodal

#include <Wire.h>

void setup()
{
    Wire.begin();
    Serial.begin(115200);
    Serial.println("\nI2C Scanner");
}

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

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

    nDevices = 0;
    for(address = 0; address <= 127; 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("Unknow 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(30000);
 }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.