EmbeddedRelated.com
Forums

Trouble Controlling MCP23017

Started by nickdesantis54 March 8, 2013
Evening all, I've been working on getting my I2C communication from an LPC2148 to an MCP32017 I/O expander and I'm running into some issues. I'm pretty confident that I've got the state machine down and that I am moving through the transactions correctly, but I cannot for the life of me get the 32017 to light up an LED.

I try transmitting according to the user manual for the LPC2148 and the datasheet for the MCP23017. I successfully get through the transmissions, getting ACKs where I should, but it doesn't want to trigger any of the pins at all and I'm not sure why.

If I've been reading correctly, the micro will get the ACKs from the I/O expander so that must mean that the data is being transmitted right?

Any input is appreciated, thanks!

An Engineer's Guide to the LPC2100 Series

The ACK does come from the slave (MCP).
I'm not familiar with the MCP32017, nor have I looked up its datasheet. However on most of these i/o expanders you need to also "tell" it which pins are output, have you done that?

--
Kevin
--- In l..., "nickdesantis54" wrote:
>
> Evening all, I've been working on getting my I2C communication from an LPC2148 to an MCP32017 I/O expander and I'm running into some issues. I'm pretty confident that I've got the state machine down and that I am moving through the transactions correctly, but I cannot for the life of me get the 32017 to light up an LED.
>
> I try transmitting according to the user manual for the LPC2148 and the datasheet for the MCP23017. I successfully get through the transmissions, getting ACKs where I should, but it doesn't want to trigger any of the pins at all and I'm not sure why.
>
> If I've been reading correctly, the micro will get the ACKs from the I/O expander so that must mean that the data is being transmitted right?
>
> Any input is appreciated, thanks!
>

The device protocol for writing is S|OP|W|ADDR|Din...Din|P

So my write operation sends a start command, then sends the slave addres + R/W bit (changes states here so I assume the ACK is received), then sends the register address I'm trying to access (state change again), and then sends the data byte and stops.

I indeed tried setting the IODIRA and IODIRB registers to all be output and then try setting half the pins to high and half to low, but something isn't working right. :(

--- In l..., "Kevin" wrote:
>
> The ACK does come from the slave (MCP).
> I'm not familiar with the MCP32017, nor have I looked up its datasheet. However on most of these i/o expanders you need to also "tell" it which pins are output, have you done that?
>
> --
> Kevin
> --- In l..., "nickdesantis54" wrote:
> >
> > Evening all, I've been working on getting my I2C communication from an LPC2148 to an MCP32017 I/O expander and I'm running into some issues. I'm pretty confident that I've got the state machine down and that I am moving through the transactions correctly, but I cannot for the life of me get the 32017 to light up an LED.
> >
> > I try transmitting according to the user manual for the LPC2148 and the datasheet for the MCP23017. I successfully get through the transmissions, getting ACKs where I should, but it doesn't want to trigger any of the pins at all and I'm not sure why.
> >
> > If I've been reading correctly, the micro will get the ACKs from the I/O expander so that must mean that the data is being transmitted right?
> >
> > Any input is appreciated, thanks!
>

I'll try to post some of my code here...

MasterTransmit(0x40, 0x00, 0x00); // IODIRA
delay_ms_t0(500);
MasterTransmit(0x40, 0x12, 0xF0); // GPIOA

I have the delay because I'm doing some UART prints to notify me when I go through each state. The MasterTransmit takes in the slave address + R/W bit, the register address, and the data.
DWORD MasterTransmit(BYTE address, BYTE reg, BYTE data)
{
ua1_puts("Set Data\n");
slaveAddress = address; //address plus write bit
I2CMasterBuffer[0] = reg;
I2CMasterBuffer[1] = data;
writeData = data;
dataLength = 2;
ua1_puts("Set Start Bit \n");
I20CONSET = I2CONSET_STA;

return (TRUE);
}

I'll try to go through the states that I go through on the write here...
case 0x08: /* A Start condition is issued. */
ua1_puts("State 0x08 State Received\n");
I20CONCLR = I2CONCLR_STAC;
I20DAT = slaveAddress;
I20CONSET = I2CONSET_AA;
I20CONCLR = I2CONCLR_SIC;
I2CMasterState = I2C_STARTED;
trans_count = 0;
recv_count = 0;
dataCounter = dataLength;
break;

case 0x18: /* Regardless, it's a ACK */
ua1_puts("State 0x18 - ACK\n");
I20DAT = I2CMasterBuffer[trans_count];
I20CONSET = I2CONSET_AA;
I20CONCLR = I2CONCLR_SIC;
trans_count++;
I2CMasterState = DATA_ACK;
break;

case 0x28: /* Data byte has been transmitted, regardless ACK or NACK */
ua1_puts("State 0x28 let's send some data\n");
dataCounter -= 1;
if(dataCounter == 0)
{
I20CONCLR = I2CONCLR_AAC;
I2CStop();
}
else
{
I20DAT = I2CSendBuffer[trans_count];
I20CONSET = 0x04;
I20CONCLR = 0x08;
trans_count++;
}
break;
So as I'm running I go through each of these states and then hit stop because I've transmitted the last of the data. Stop function follows.

DWORD I2CStop( void )
{
ua1_puts("Stop Called\n");

I20CONSET = 0x14; /* Set Stop flag */
I20CONCLR = I2CONCLR_SIC; /* Clear SI flag */
return TRUE;
}
I must be receiving ACKs because I'm changing states, but for some reason I cannot simply set my MCP23017 pins to output and then light an LED with any of them.

Just written some code for this chip...

If you are getting ack your I2C code must be all right.

You need to write both registers 0x00 and 0x01 to 0x00, to set the pins to output (not to 0xFF as I expected)
Then write registers 0x12 and 0x13 to set the output states
--
Tim Mitchell
Make sure that the MCP23017 register map that you are using matches how you have the bank bit set in the IOCON register.

Jeff

--- In l..., "nickdesantis54" wrote:
>
> Evening all, I've been working on getting my I2C communication from an LPC2148 to an MCP32017 I/O expander and I'm running into some issues. I'm pretty confident that I've got the state machine down and that I am moving through the transactions correctly, but I cannot for the life of me get the 32017 to light up an LED.
>
> I try transmitting according to the user manual for the LPC2148 and the datasheet for the MCP23017. I successfully get through the transmissions, getting ACKs where I should, but it doesn't want to trigger any of the pins at all and I'm not sure why.
>
> If I've been reading correctly, the micro will get the ACKs from the I/O expander so that must mean that the data is being transmitted right?
>
> Any input is appreciated, thanks!
>

I was able to get a hold of an oscilloscope today and checked out my SDA and SCL lines... it looks like when I am trying to send a start condition that my clock is low, so it doesn't register as a clock... that or I'm doing something wrong with the scope. Does anyone have experience analyzing i2c using an O-Scope?

useing a scope to analyse I2C is possible, if it's a digital storage scope. I'm assuming it is and I also assume that you know how to use a scope.

I suggest using "normal" trigger mode instead of auto. Trigger on the falling edge of the SCL.

If you do see pulses/bits but idle stays low, then you probably have messed up the STOP.

If possible I would suggest using a logic-analyzer and preferably one with parsers for I2C.

--
Kevin

--- In l..., "nickdesantis54" wrote:
>
> I was able to get a hold of an oscilloscope today and checked out my SDA and SCL lines... it looks like when I am trying to send a start condition that my clock is low, so it doesn't register as a clock... that or I'm doing something wrong with the scope. Does anyone have experience analyzing i2c using an O-Scope?
>

I have to confess, I had so much trouble getting the I2C peripheral to work properly that I wrote a bit-bang version instead for simple IO/eeprom type parts.

--
Tim Mitchell
> I have to confess, I had so much trouble getting the I2C peripheral to
> work properly that I wrote a bit-bang version instead for simple IO/eeprom
> type parts.

LPC812 has I2C drivers in ROM for even more fun! ;-)

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
SolderCore Development Platform http://www.soldercore.com