Programmatically determine what is on the i2c line

i2c

I'm working on a project that uses a simple microcontroller (I2C) master, and a component (I2C slave). When the microcontroller receives power the first thing it has to do is determine which device is on the I2C line. Only one device on the line is expected.

How would one go about determining which device is on the I2C line?

I've thought of a few ways:

  1. Try all possible addresses for items, then search for the device ID in each item. (I've found the location of the device ID register is different on most chips).
  2. Send out a Device ID request – but the spec says this is optional. And I couldn't find anyone relying on this.
  3. Uniquely address each component, create a map. (i.e. This address means it must be this component.) Try each address.

For additional context, once the device is determined, capabilities are mapped in the firmware and the firmware executes.

Solution 1 sounds like a brute force approach. I'd like this to be fast, and this doesn't seem fast.

Solution 2 sounds unreliable- but maybe that's only because of my lack of experience.

Solution 3 seems possible, but then I'm limited to the number of I2C devices the address space can support.

Best Answer

Scanning all possible addresses is probably the most straightforward, assuming you don't know what the slave address is beforehand. I2C is not all that slow (100s of kbit/sec) so scanning through 128 addresses will not take much time at all.

Now, after you've identified which addresses are accessible on the bus, the next step is actually communicating with them. This is why scanning is not usually done over the entire range - generally the firmware only knows how to talk to a few devices, and the addresses for these devices are hard-coded in the firmware. This is the case because generally I2C device addresses are not very flexible - they're either completely fixed, or mostly fixed with a couple of bits settable via pin strapping. This generally means you're stuck with solution 3 by default.