# How to reliably read register positions from an MCP23017 over I2C?

I am using a MCP2221 to talk I2C to a MCP23017. Using python3 to interface.

I had some trouble with the adafruit libraries, so have resorted to using the PyMCP2221A library. It works great for writing to the MCP23017. However, I don't know how to ensure I am reading the correct position of the MCP23017 registers.

For example in the MCP2221 I2C Terminal software I ran the following series of commands. If I read just one bit (say that is a bus error, emf issue, or other) then the buffer in the MCP23017 does not reset itself and the data becomes shifted and I will read the data in the incorrect register.

Looking at the adafruit mcp23017 code it looks like they reset the transmission just before reading. This makes sense, but not sure how to do that in python or how to access this I2C stop function from the PyMCP2221A library or the upstream cython-hidapi library. Also not 100% sure it just requires a stop signal or something more.

/**
*/
_wire->endTransmission();
return wirerecv(_wire);
}


Any guidance is greatly appreciated!

Unlike reading, the writing process is quite simple:

1. Send start
2. Send device address on writing (0 1 0 0 A2 A1 A0 0)
3. Send register address (for example: 00h)
4. Send byte-by-byte (the register counter will increment automatically)

According to the pg.14-pg.15 of the datasheet on the MCP23017, for reading you shall:

1. Send start
2. Send device address on writing (0 1 0 0 A2 A1 A0 0)
3. Send register address (this action set the register counter and determ the reading position, for example: 00h)
4. Send stop
5. Send start (again)
6. Send device addres on reading (0 1 0 0 A2 A1 A0 1)
7. Read sequentially all nessesary registers

• You sir are a genius! I have no idea how you extracted that information from the datasheet. And it took a while to soak in to my mind. I tested it this evening and it worked perfectly resetting the address pointer to the zero register! Thank You! > I2C Write, Address = 32, Data: 0 Delay = 0 – ericnutsch Sep 3 '20 at 6:24
• A couple years ago I myself was looking for an answer to this question. No problems ;) – Arseniy Sep 3 '20 at 6:27
• Microchip support did reply, but essentially told me RTFM lol. Understanding that part was definitely not intuitive. Thanks again! – ericnutsch Sep 3 '20 at 6:45

The accepted answer is great, but has an error. For the read sequence, step 4 (Send Stop) should not be issued. The highlighted diagram (red rectangles) actually shows no stop sent after address (ADDR) and before a restart (SR). Transmitting a stop at this point signals other masters that the bus is free and they are open to taking control of the bus. This could result in an arbitration error being generated when the start at point 5 in this example is issued.

The actual steps for a read are:

1. Start (S)
2. Transmit OP | W ((OP << 1) | 0)