Datasheet

Using the MCP23008 I/O Expander
29
The MCP23008 I/O Expander is a more complex device[MCP5]. It has eight I/O pins, each of which may
be configured as an input or an output. This makes it useful when a large number of I/O devices are
required and speed is not an issue (I
2
C can only send thousands of commands a second, compared to
millions of changes or tests per second possible directly to a port). Since the possible addresses allow for
eight devices, a total of 64 digital I/O pins may be supported on a single I
2
C bus.
The device has 11 registers that may be read or written. In most cases, only three of these registers
are of interest; the IODIR register, comparable to the TRIS registers in the PIC, the GPIO register,
comparable to the PORT registers in the PIC, and the OLAT register, comparable to the PIC LAT registers.
The remaining registers allow for setting weak pull-ups on inputs, setting default states for outputs, and
allowing for interrupt on change.
The include file, MCP23008.h includes definitions for all the registers as well as function prototypes for
the two provided functions, MCP23008writeRegister() and MCP23008readRegister(). As with all
I
2
C functions, i2c.h must also be included so that InitI2C() may be called:
#include "../include/i2c.h"
#include "../include/MCP23008.h"
If only input is required, calling MCP23008readRegister() fetches the current state of the pins:
InitI2C();
/* Get the current state of the I/O expander's pins */
ucPortState = MCP23008readRegister( 0x20, MCP23008_GPIO );
The I/O extender defaults to input mode on power up.
For writing, the I/O direction register must first be set to make the desired pins be outputs. Like the PIC, a
0 bit sets the pin to be an output, so to make all pins outputs:
MCP23008writeRegister( 0X20, MCP23008_IODIR, 0x00 );
Consider a case with a button on pin 1, and an LED on pin 4. To light the LED whenever the button was
pressed. Our code might look something like:
unsigned char ucPortValue;
/* Initialize I2C and the MCP23008 */
InitI2C();
MCP23008writeRegister( 0X20, MCP23008_IODIR, 0xef );
while ( 1 )
{
/* Get the state of the button */
ucPortValue = MCP23008readRegister( 0x20, MCP23008_GPIO );
/* Is the button pressed? */
if ( ucPortValue & 0x02 )
/* Yes, turn on the LED */
MCP23008writeRegister( 0X20, MCP23008_OLAT, 0x10 );
else
/* No, turn off the LED */
MCP23008writeRegister( 0X20, MCP23008_OLAT, 0x00 );
}