5
\$\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\$
6
  • 1
    \$\begingroup\$ Same way as finding the IP address of an arbitrary host: The hard way. \$\endgroup\$ Commented Jul 21, 2013 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
    Commented Jul 21, 2013 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
    Commented Jul 21, 2013 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
    Commented Jul 22, 2013 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\$ Commented Jul 22, 2013 at 12:54

4 Answers 4

13
\$\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\$
3
  • \$\begingroup\$ Just a side note, knowing what the i2c device does would also help. For example, i2c Eeproms can ack multiple addresses. \$\endgroup\$
    – Passerby
    Commented Jul 21, 2013 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
    Commented Jul 21, 2013 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
    Commented Jul 21, 2013 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\$
0
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\$

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