I2C Help [MCP23017]

10 Apr 2012

Hey guys and gals, I have a MCP23017 and I'm using Jim Herd's library found Here. I am using the following code:

#include "mbed.h"
#include "MCP23017.h"

DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);

//I2C i2cX( p9, p10);

MCP23017 *xController;

int main() {
    xController = new MCP23017( p9, p10, 0x00);
    // I2C init
    //i2cX.frequency(100000);
    
    xController->config(0,0,0);
    
    myled3 = 1;
    wait(1);
    myled3 = 0;
    int x;
    
    while(1) {
        myled1 = 1;
        myled2 = 0;
        for (x = 0; x < 16; x++){
            xController->write_bit(0,x);
        }
        wait(1);
           
        myled1 = 0;
        myled2 = 1;
        for (x = 0; x < 16; x++){
            xController->write_bit(1,x);
        }     
        wait(1);
    }
}

For data connections, I have sda to pin 9, scl to pin 10, 3.3k pullup to 3.3V from both data lines, Vss / A0/A1/A2 to GND, Vdd to +3.3V. What am I missing here to get this working? The values of all the pins are 0.08V and that doesn't change.

I'm on a short deadline so anything to get me started or fix it I'd really appreciate it.

EDIT:: I don't believe I make my own I2C variable, _i2c is in the library

12 Apr 2012

Your problem is the I2C slave address. The MCP base address is 0x40, which is also the slave address in your case (A0,A1,A2=0). Your declaration code uses 0x00:

xController = new MCP23017( p9, p10, 0x00)

this should be:

xController = new MCP23017( p9, p10, 0x40)

13 Apr 2012

Wim, thank you so much for the help. That was exactly it. I was so frustrated looking over my hardware over and over. Now that I think back, the example code I found from you had 0x40 and for some reason I thought it was for a different address. My mistake.

Thanks again for all the help, so glad to see this working!

Edit:: If you don't mind one more question, does INTA / INTB matter? I have 2 chips so I'll be using 0x40 / 0x41. Thanks!

13 Apr 2012

INTA and INTB may be used to generate an interrupt on the mbed on any bitlevel changes on input pins of the MCP. You dont need to connect them when interrupts are not used and you just poll the ports. You can configure the INTA/B pins to either respond to events on port A and port B separately or respond to on an event on either one. First option is useful when A and B are used as separate 8 bit ports, second one is more useful when you are in 16 bit mode.

When using two MCPs the addresses are 0x40 and 0x42. Note that the A0-A1-A2 selectbits are shifted up by one bitposition. This is due to the fact that the I2C slave addressbit 0 is always used to distinguish between read and write operations.

13 Apr 2012

So if I have A2 A1 A0 as 0 0 1 for the second device, that is 0x42?

13 Apr 2012

Jesse Ardonne wrote:

So if I have A2 A1 A0 as 0 0 1 for the second device, that is 0x42?

Correct.

Check Fig 1-2 or 1-4 in the datasheet. Slave address definition is a bit confusing in the I2C world. Some people use a 7 bit address in documentation and software. They assume an implicit shift left by the software and an inserted bit 0 for R/W. Most people, including me, always use an 8 bit address description and the software replaces bit 0 by the R/W bit.

13 Apr 2012

Alright, so I would have in my code:

    MCP23017 MCP1 = MCP23017( p9, p10, 0x00);
    MCP23017 MCP2 = MCP23017( p9, p10, 0x02);

And that would be fine? I already have both of them on the same data lines with 1 pull up 3.3k resistor per line. The data sheet is a little over my head although I'll continue looking into it. Thanks Wim!

13 Apr 2012

Jesse Ardonne wrote:

Alright, so I would have in my code:

    MCP23017 MCP1 = MCP23017( p9, p10, 0x00);
    MCP23017 MCP2 = MCP23017( p9, p10, 0x02);

And that would be fine?

Nope, not correct. You have the same wrong address again. Should be:

    MCP23017 MCP1 = MCP23017( p9, p10, 0x40);
    MCP23017 MCP2 = MCP23017( p9, p10, 0x42);

And yes, you hook up p9, p10 to both MCPs with one pull-up per line.

13 Apr 2012

Oh yes, the 4, my apologies. I just got in a shipment of 5 because these things are $2 and are so useful. If I wanted to hook all the way up to 8, what addresses would I use?

0x40 | 0x42 | 0x44 | 0x46 | 0x48 | 0x4A | 0x4C | 0x4E

Is that correct? Thanks Wim!