Reading multiple pins from MCP23017
Moderators: adafruit_support_bill, adafruit

Reading multiple pins from MCP23017

by seamus on Thu Dec 06, 2012 8:36 pm

I've got a 12-bit binary ripple counter whose outputs are feeding an MCP23017 16-bit I2C port expander chip (bits 0-7 on port A, bits 8-11 on the first 4 bits of port B). So far, I've got it all up and working, counting away in the background, and letting me see what the count is on demand via I2C (hooray!).

Having worked through the examples supplied in the library, I know how to read and write a single pin at a time, and I have successfully used this to assemble the bits into meaningful data one bit at a time. It seems a bit wasteful and redundant, however, to be pulling the data in as bytes via I2C and breaking them up into individual pin readings with mcp.digitalRead(x), only to turn right around and spend several additional lines of code to reassemble them into bytes again in order to use the data.

Ideally, I would like to be able to read both A and half of the B ports as a 12-bit value, while still retaining one I/O line as an output for resetting the counter.
Alternately, I could read A and the lower nibble of B as bytes and assemble them, which would still be fewer operations than my current method of reading 12 digital lines sequentially.

I have been through the files in the Adafruit MCP23017 library, and have not yet been able to figure out how to read the Port A and B values as bytes in a single shot, if it is in fact possible.

Any assistance in this matter would be greatly appreciated.
I make things.
Sometimes I break things too.
...because variety is good.

seamus
 
Posts: 40
Joined: Sun Nov 23, 2008 2:18 am
Location: Upstate SC

Re: Reading multiple pins from MCP23017

by adafruit_support_rick on Wed Dec 12, 2012 12:45 pm

You can use readGPIOAB and writeGPIOAB to access the data registers 16 bits at a time.
Code: Select all | TOGGLE FULL SIZE
uint16_t Adafruit_MCP23017::readGPIOAB() {
  uint16_t ba = 0;
  uint8_t a;

  // read the current GPIO output latches
  Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
  wiresend(MCP23017_GPIOA);   
  Wire.endTransmission();
 
  Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 2);
  a = wirerecv();
  ba = wirerecv();
  ba <<= 8;
  ba |= a;

  return ba;
}

void Adafruit_MCP23017::writeGPIOAB(uint16_t ba) {
  Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
  wiresend(MCP23017_GPIOA);   
  wiresend(ba & 0xFF);
  wiresend(ba >> 8);
  Wire.endTransmission();
}

adafruit_support_rick
 
Posts: 13837
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: Reading multiple pins from MCP23017

by seamus on Tue Dec 18, 2012 5:27 pm

Thanks for the reply. Sorry it took me so long to see it - I lost the motherboard on my main computer last week, and I'm still getting things sorted back out again.

Actually, as I was playing with the circuit, I realized that the wiring could be greatly simplified if I were to route the binary counter's outputs straight over physically, and then read the port expander's pins individually in order to descramble the order in software. It takes a few more instructions, and a little more time, but the trade-off is that the protoboard layout and wiring is a lot simpler and more compact, in a location where I don't have a lot of space to play with.

Thanks for the help, and I'll be sure to remember it for next time, when I'm sure to have a little more room to work with.

Image

seamus
 
Posts: 40
Joined: Sun Nov 23, 2008 2:18 am
Location: Upstate SC