The MCP23XXX device family provides 8/16-bit, general purpose parallel I/O expansion for I2C or SPI applications. These devices include a range of addressing schemes and I/O configurations including pull-up resistors, polarity inverting, and interrupts.
- The docuementation from Adafruit
- Learn how to use MCP23008 and MCP23017 with Python from the Adafruit learn courses used to create this binding.
MCP23XXX devices contain different markings to distinguish features like interfacing, packaging, and temperature ratings. For example, MCP23017 contains an I2C interface and MCP23S17 contains a SPI interface. Please review specific datasheet for more information.
NOTE: MCP23X16 contains different internal circuitry and is not compatible with this binding.
// 0x20 is the device address in this example.
var connectionSettings = new I2cConnectionSettings(1, 0x20);
var i2cDevice = I2cDevice.Create(connectionSettings);
var mcp23S17 = new Mcp23017(i2cDevice);
var connectionSettings = new SpiConnectionSettings(0, 0)
{
ClockFrequency = 1000000,
Mode = SpiMode.Mode0
};
var spiDevice = SpiDevice.Create(connectionSettings);
// 0x20 is the device address in this example.
var mcp23S17 = new Mcp23S17(spiDevice, 0x20);
On 16-bit expanders the GPIO ports are grouped into 2 "ports". Via the IGpioController
interface we expose the pins logically as 0-15, with the first bank being 0-7 and the second being 8-15.
When using ReadByte()
or WriteByte()
on the 16-bit chips you can specify PortA
or PortB
to write to respective registers. The default is PortA
. Reading and writing ushort
writes to both ports.
The internal circuitry has a banking concept to group by port registers or by register type. This enables different configurations for reading/writing schemes. While we have some support for the bank styles it is not exposed directly. There is no safe way to detect the mode and most other drivers do not support anything but the defaults. You need to derive from Mcp23xxx
directly.
// Read Port B's Input Polarity Port Register (IPOL).
byte data = mcp23S17.Read(Register.IPOL, Port.PortB);
The MCP23X08 only contains 1 port so there is not a choice for port when addressing the register.
// Read port A's GPIO Pull-Up Resistor Register (GPPU).
byte data = mcp23S08.ReadByte(Register.GPPU);
The Mcp23xxx
has overloaded pin options when instantiating the device. This includes a reset line, which is an output pin of the controller to the MCP23XXX RST input pin. The other pins are interrupt options, which are inputs to the controller from the MCP23XXX INTA/INTB output pins. They are optional arguments. Assign as null
for the pins you don't use.
// Pin 10: Reset; Output to Mcp23xxx
// Pin 25: INTA; Input from Mcp23xxx
// Pin 17: INTB; Input from Mcp23xxx
var mcp23S17 = new Mcp23S17(spiDevice, 0x20, 10, 25, 17);
The MCP23XXX will be in the reset/disabled state by default if you use the reset pin. You must call the Enable()
method to activate the device.
var mcp23S17 = new Mcp23S17(spiDevice, 0x20, 10, 25, 17);
mcp23S17.Enable();
// Can now communicate with device.
// Turn off again if needed.
mcp23S17.Disable();
The Mcp23xxx
has one (8-bit variants) or two (16-bit variants) interrupt pins. These allow external
signalisation on interrupt change. The corresponding pins need to be connected to a master GPIO controller
for this feature to work. You can use a GPIO controller around the MCP device to handle everything
for you:
// Gpio controller from parent device (eg. Raspberry Pi)
_gpioController = new GpioController(PinNumberingScheme.Logical);
_i2c = I2cDevice.Create(new I2cConnectionSettings(1, 0x21));
// The "InterruptA" line of the Mcp23017 is connected to GPIO input 11 of the Raspi
_device = new Mcp23017(_i2c, -1, 11, -1, _gpioController, false);
GpioController theDeviceController = new GpioController(PinNumberingScheme.Logical, _device);
theDeviceController.OpenPin(1, PinMode.Input);
theDeviceController.RegisterCallbackForPinValueChangedEvent(1, PinEventTypes.Rising, Callback);
Alternatively, you can also manually control the event handling:
_gpioController = new GpioController();
_device = I2cDevice.Create(new I2cConnectionSettings(1, 0x21));
// Interrupt pin B is connected to GPIO pin 22
_mcp23017 = new Mcp23017(_device, -1, -1, 22, gpioController, false);
_mcp23017.EnableInterruptOnChange(8, PinEventTypes.Rising | PinEventTypes.Falling); // Enable interrupt for pin 8
_gpioController.RegisterCallbackForPinValueChangedEvent(22, PinEventTypes.Falling, Interrupt);
// Read the interrupt register, to make sure we get any further interrupts
_mcp23017.ReadByte(Register.GPIO, Port.PortB);
This binding includes an Mcp23xxx
abstract class and derived abstract classes for 8-bit Mcp23x0x
and 16-bit Mcp23x1x
variants.