Test I2C Interface

How do i test an I2C interface…i have my fez cobra 2 connected to a MCP23017 chip using i2c…how do i test this interface. This code is failing…

   //create I2C object
          //note that the netmf i2cdevice configuration requires a 7-bit address! It set the 8th R/W bit automatically.
          I2CDevice.Configuration con =
             new I2CDevice.Configuration(0x38, 400);
          I2CDevice MyI2C = new I2CDevice(con);
 
          // Create transactions
          // We need 2 in this example, we are reading from the device
          // First transaction is writing the "read command"
          // Second transaction is reading the data
          I2CDevice.I2CTransaction[] xActions =
             new I2CDevice.I2CTransaction[2];
 
          // create write buffer (we need one byte)
          byte[] RegisterNum = new byte[1] { 2 };
          xActions[0] = I2CDevice.CreateWriteTransaction(RegisterNum);
          // create read buffer to read the register
          byte[] RegisterValue = new byte[1];
          xActions[1] = I2CDevice.CreateReadTransaction(RegisterValue);
 
          // Now we access the I2C bus using a timeout of one second
          // if the execute command returns zero, the transaction failed (this
          // is a good check to make sure that you are communicating with the device correctly
          // and dont have a wiring issue or other problem with the I2C device)
          if (MyI2C.Execute(xActions, 1000) == 0)
          {
              Debug.Print("Failed to perform I2C transaction"); //reaches here
          }
          else
          {
              Debug.Print("Register value: " + RegisterValue[0].ToString());
          }
      }
   }
}

I am not sure how reliable is the return value. I have never used it. Is the address value correct for that device?

By the way we have a driver on codeshare for a similar device:

https://www.ghielectronics.com/community/codeshare/entry/395

The return address is very reliable.

The address of this device is not 0x38. From section 1.4 of the datasheet, the address is 0100xxx where the three unknowns are based on the address line settings. Assuming they’re all pulled to GND, that will be 0100000, or 0x20.

1 Like

I was talking about return value of the Execute method that he is checking in the code. Wrong address was my bet as well. Good find!

As was I, although I didn’t notice I typed “address” not “value”. Whoopsies.

But yes, I can’t remember the last time I saw a I2C issue come up that didn’t have an address element to it :wink:

A1,A2 -> GND
A0 -> HIGH

So address is 0x21

I have analysised the data lines on the physical board and not matter what i do on the ic2 bus the data being sent is always 42 Any suggestion

So it’d be great if you can tell us, is 42 decimal or hex (or octal, but that’s not likely :slight_smile: )

If you’re seeing an 0x42, or 42 decimal, still doesn’t make sense to me. Can I ask have you checked your pull up resistors?

So I’m assuming you’re using a logic analyser and are checking the CLK line at the same time yeah? You should see a start bit (SDA transition high to lo with SCL high) then followed by the start of the CLK toggling - you should get an 01000010 (assuming a WRITE operation). I’ll dig out a device and the logic analyser and check what I get.

ok…made progress…42 is the address of the i2c device. So its send the request but i do not get any form of akowledgement.

Actually, 0x42 is the full control byte that implies you’re doing a write. You’ll see 0x43 if you issue a read first.

I have a working repro of this now with my LA. Here’s the code I used


        public static void Main()
        {
            
            I2CDevice i2c = null; 
            I2CDevice.I2CTransaction[] writeTrans = new I2CDevice.I2CTransaction[1]; 
            I2CDevice.I2CTransaction[] readTrans = new I2CDevice.I2CTransaction[2]; 
            OutputPort resetPin = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di8,false);
            OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false);

            byte[] singleCommand = new byte[1]; 
            byte[] writeBuffer = new byte[2]; 
            byte[] readBuffer = new byte[1];

            int retval;

            I2CDevice.Configuration config = new I2CDevice.Configuration(0x21, 400);
            i2c = new I2CDevice(config);

            writeBuffer[0] = 0x00;
            writeBuffer[1] = 0xff;
            writeTrans[0] = I2CDevice.CreateWriteTransaction(writeBuffer);

            while (true)
            {
                Thread.Sleep(2000);

                resetPin.Write(true); // toggle my trigger pin!
                led.Write(true);

                retval = i2c.Execute(writeTrans, 100);

                resetPin.Write(false); // toggle my trigger pin!
                led.Write(false);

                Debug.Print("Returned: " + retval);
            }

//            Thread.Sleep(Timeout.Infinite);

        }

As you can see I just loop through this with a 2sec pause between writes. My Writes are meant to write the IO Direction register to 0xff (this is the first step of the initialisation routine, based on the codeshare code Architect pointed out earlier). I toggle the LED and a trigger pin that I’m using to trigger the LA at the start of the loop, then clear them at the end.

When I decode the I2C data I can see I don’t get an ACK, which is expected since I don’t have the device.

So now I reckon I’d be checking the device pins you have wired correctly (SDA and SCL), and potentially check the RESET pin of the chip to make sure that’s connected in accordance with the datasheet. You’ve never told us if you’re using a commercial breakout board, so if it’s a homemade thing I’d be checking the soldering for dry/missed joints.

@ Brett thank you very much…will try your code.