Device driver for Microchip MCP23x17 I/O expanders. More...
Device driver for Microchip MCP23x17 I/O expanders.
Microchip MCP23x17 I/O expanders provide general purpose I/O extension over I2C or SPI. The driver supports the following MCP23x17 I/O expander and interface variants:
Expander | Type | Interface | Pseudomodule to be used |
---|---|---|---|
MCP23017 | 16-bit I/O expander | I2C | mcp23017 or mcp23x17_i2c |
MCP23S17 | 16-bit I/O expander | SPI | mcp23s17 or mcp23x17_spi |
For each of the MCP23x17 interface variant, the driver defines a separate pseudomodule. Multiple MCP23x17 I/O expanders and different interface variants can be used simultaneously. The application has to specify used MCP23x17 I/O expander or interface variants as a list of used pseudomodules. For example, to use a MCP23017 with I2C interface and a MCP23S17 with SPI interface at the same time, the make command would be:
At least one MCP23x17 I/O expander or interface variant has to be specified. The driver module mcp23x17
is then enabled implicitly.
The driver interface is kept as compatible as possible with the peripheral GPIO interface. The only differences are that
mcp23x17_
andThe functionality of the driver is controlled by the use of pseudomodules. The following pseudomodules are defined:
Pseudomoule | Functionality |
---|---|
mcp23017 | support of MCP23017 with I2C interface |
mcp23x17_i2c | support of MCP23017 with I2C interface |
mcp23s17 | support of MCP23S17 with SPI interface |
mcp23x17_spi | support of MCP23S17 with SPI interface |
mcp23x17_irq | support of interrupts enabled with medium event priority |
mcp23x17_irq_medium | support of interrupts enabled with medium event priority |
mcp23x17_irq_highest | support of interrupts enabled with highest event priority |
mcp23x17_reset | support of hardware reset (RESET pin is used) |
mcp23017
, mcp23x17_i2c
, mcp23s17
or mcp23x17_spi
has to be used.mcp23017
enables the mcp23x17_i2c
module automatically.mcp23s17
enables the mcp23x17_spi
module automatically.mcp23x17_irq
enables the mcp23x17_irq_medium
module automatically if no other `mcp23x17_irq_*
module is enabled.The MCP23x17 expander devices provide 16 bidirectional input/output (I/O) pins. These pins are arranged in two ports A and B with 8 pins each. Each expander I/O pin can be used as input or output. Weak pull-up resistors can be enabled for input pins. Output pins are latched.
The driver supports the following GPIO modes:
GPIO mode | Remarks |
---|---|
GPIO_IN | supported by the MCP27x17 expander device |
GPIO_IN_PU | supported by the MCP27x17 expander device |
GPIO_IN_PD | not supported |
GPIO_OUT | supported by the MCP27x17 expander device |
GPIO_OD | emulated by the driver |
GPIO_OD_PU | emulated by the driver |
After the initialization with function mcp23x17_init, all MCP23x17 expander I/O pins are in GPIO_IN mode.
The MCP23x17 expander I/O pins for each device can be addressed either consecutively in the range of 0 ... 15 or by using the macro MCP23X17_GPIO_PIN with the tuple (port, pin) according to the following scheme:
MCP23x17 pin label | Expander Port | Expander Pin | RIOT symbol |
---|---|---|---|
GPA0 | 0 | 0 | MCP23X17_GPIO_PIN(0, 0) |
GPA1 | 0 | 1 | MCP23X17_GPIO_PIN(0, 1) |
... | ... | ... | ... |
GPA7 | 0 | 7 | MCP23X17_GPIO_PIN(0, 7) |
GPB0 | 1 | 0 | MCP23X17_GPIO_PIN(1, 0) |
GPB1 | 1 | 1 | MCP23X17_GPIO_PIN(1, 1) |
... | ... | ... | ... |
GPB7 | 1 | 7 | MCP23X17_GPIO_PIN(1, 7) |
MCP23x17 I/O expanders can be connected either via I2C or via SPI. The interface of the respective device is defined by the configuration parameter mcp23x17_if_params_t::type, which can be either MCP23X17_SPI or MCP23X17_I2C. To use these interface types, the corresponding modules mcp23x17_spi
and/or mcp23x17_i2c
have to be enabled.
Each MCP23x17 device requires an address which is configured via the hardware address pins A0 ... A2 of the MCP23x17 device. The address is in the range from 0 to 7 and is used internally by the driver as an offset to the base address MCP23X17_BASE_ADDR to derive the full device address.
In addition to the type and the address of the interface, a number of interface specific parameters have to be configured for each device:
Interface | Parameter | Parameter |
---|---|---|
SPI | Device Identifier | mcp23x17_if_params_t::if_params.spi.dev |
SPI | Chip Select GPIO | mcp23x17_if_params_t::if_params.spi.cs |
SPI | Clock Rate | mcp23x17_if_params_t::if_params.spi.clk |
SPI | Address Offset | mcp23x17_params_t::addr |
I2C | Device Identifier | mcp23x17_if_params_t::if_params.i2c.dev |
I2C | Address Offset | mcp23x17_params_t::addr |
MCP23x17 I/O expanders have a low-active RESET
pin. If module mcp23x17_reset
is used, a hardware reset is executed when the expander device is initialized with function mcp23x17_init. Otherwise, only power on reset configuration is restored.
If the hardware reset is used by enabling module mcp23x17_reset
, the configuration parameter mcp23x17_params_t::reset_pin has to define the MCU GPIO pin that is connected to the RESET
pin of MCP23x17 devices.
MCP23x17 expanders have two interrupt pins INTA
and INTB
, one for each port. These interrupt pins are internally connected (mirrored) by the driver so that an interrupt on either port will cause both pins to activate. Thus, interrupts on either port can be handled using a single interrupt pin connected to the MCU.
The configuration parameter mcp23x17_params_t::int_pin is used to configure the MCU pin that is connected to one of the interrupt pins INTA
or INTB
. Each MCP23x17 expander device must use its own GPIO pin for its combined INTA
/INTB
signal.
An interrupt callback function can be attached to an expander input pin with the mcp23x17_gpio_init_int function. This interrupt callback function is then called on any rising and/or falling edge of the expander input pin.
To be able to handle interrupts in thread context, a separate event thread is used, see section The Interrupt Context Problem. Therefore, enabling interrupts requires more RAM and interrupts have to be explicitly enabled with the module mcp23x17_irq_<priority>
. priority
can be one medium
or highest
, which correspond to the priority of the event thread that processes the interrupts. For more information on the priorities check Event Queue module.
mxp23x17_irq
without specifying the priority. In this case, module mcp23x17_irq_medium
is enabled automatically and the interrupt support is enabled with a medium priority of the event thread.Furthermore, the GPIO pin to which the combined MCP23x17 INTA
/INTB
signal is connected has to be defined by the parameter mcp23x17_params_t::int_pin. The default hardware configuration as defined in mcp23x17_params.h
defines by
For more information about the default hardware configuration, see section Default Hardware Configuration.
This default configuration could be overridden at make command line, for example to use a MCP23017 with I2C interface and interrupt support with high priority:
Handling an interrupt of a MCP23x17 expander requires the driver to access the device directly via I2Cor SPI. However, the mutex-based synchronization of I2C and SPI accesses do not work in the interrupt context. Therefore the ISR must not access the MCP23x17 expander device directly. Rather, the ISR must only indicate the occurrence of the interrupt which has to be handled asynchronously in the thread context.
For this purpose an event thread module is used when interrupts are enabled by the module mcp23x17_irq_<priority>
. The driver then handles the interrupts in the context of the event thread with given priority
. For more information on the priorities check the Event Queue module.
The driver provides SAUL capabilities that are compatible to the SAUL capabilities of MCU GPIOs. Each MCP23x17 expander I/O pin can be mapped directly to SAUL by defining an according entry in MCP23X17_SAUL_GPIO_PARAMS. Please refer file mcp23x17_params.h
for an example.
saul_gpio
has to be added to the project to enable SAUL capabilities of the MCP23x17 driver, e.g., It is possible to use multiple devices and different interface variants of MCP23x17 I/O expanders simultaneously. The application has to specify used interface variants by a list of pseudomodules. For example, to use MCP23017 and MCP23S17 I/O expanders simultaneously, the make command would be:
Furthermore, used devices have to be configured by defining the hardware configuration parameter array mcp23x17_params
of type mcp23x17_params_t. A default hardware configuration for one device of each interface variant is already defined in mcp23x17_params.h
.
The application can override it by placing a mcp23x17_params.h
* in the application directory . For example, the definition of the hardware configuration parameter array for two devices with SPI interface and two devices with I2C interface could be:
The default hardware configuration is defined in file mcp23x17_params.h
using the following defines:
Hardware configuration | Driver name | Default Value |
---|---|---|
SPI Address Offset | MCP23X17_PARAM_SPI_ADDR | 0 |
SPI Device Identifier | MCP23X17_PARAM_SPI_DEV | SPI_DEV(0) |
SPI Clock rRate | MCP23X17_PARAM_SPI_CLK | SPI_CLK_10MHZ |
SPI Chip Select GPIO | MCP23X17_PARAM_SPI_CS | GPIO_PIN(0,0) |
SPI Device INTA /INTB GPIO | MCP23X17_PARAM_SPI_INT | GPIO_PIN(0,1) |
I2C Address Offset | MCP23X17_PARAM_I2C_ADDR | 0 |
I2C Device Identifier | MCP23X17_PARAM_I2C_DEV | I2C_DEV(0) |
I2C Device INTA /INTB GPIO | MCP23X17_PARAM_I2C_INT | GPIO_PIN(0,2) |
RESET GPIO for all devices | MCP23X17_PARAM_RESET_PIN | GPIO_UNDEF |
These default hardware configuration parameters can be overridden either by the board definition or by defining them in the CFLAGS
variable in the make command, for example:
Files | |
file | mcp23x17.h |
Device driver interface for Microchip MCP23x17 I/O expanders. | |
file | mcp23x17_params.h |
Default configuration for Microchip MCP23x17 I/O expanders. | |
file | mcp23x17_regs.h |
Register definitions for Microchip MCP23x17 I/O expanders. | |
Data Structures | |
struct | mcp23x17_i2c_params_t |
MCP23017 I2C parameters. More... | |
struct | mcp23x17_spi_params_t |
MCP23S17 SPI parameters. More... | |
struct | mcp23x17_if_params_t |
MCP23x17 Hardware interface parameters union. More... | |
struct | mcp23x17_params_t |
Struct containing the peripheral configuration. More... | |
struct | mcp23x17_irq_event_t |
IRQ event type. More... | |
struct | mcp23x17_t |
Device descriptor for MCP23x17 I/O expanders. More... | |
struct | mcp23x17_saul_gpio_params_t |
MCP23x17 configuration structure for mapping expander pins to SAUL. More... | |
Macros | |
#define | MCP23X17_BASE_ADDR (0x20) |
MCP23x17 device base address. More... | |
#define | MCP23X17_GPIO_PIN_NUM (16) |
MCP23x17 has 16 I/O pins. | |
#define | MCP23X17_GPIO_PIN(port, pin) ((gpio_t)((port << 3) | pin)) |
Conversion of (port x : pin y) to a pin number. More... | |
Enumerations | |
enum | mcp23x17_error_codes_t { MCP23X17_OK , MCP23X17_ERROR_I2C , MCP23X17_ERROR_SPI , MCP23X17_ERROR_NO_DEV , MCP23X17_ERROR_INV_MODE , MCP23X17_ERROR_INV_FLANK , MCP23X17_ERROR_GPIO , MCP23X17_ERROR_INT_PIN , MCP23X17_ERROR_RESET_PIN } |
Named MCP23x17 driver error codes. More... | |
enum | mcp23x17_if_t { MCP23X17_I2C , MCP23X17_SPI } |
MCP23x17 interface types. More... | |
Functions | |
int | mcp23x17_init (mcp23x17_t *dev, const mcp23x17_params_t *params) |
Initialize the MCP23x17 I/O expander. More... | |
int | mcp23x17_gpio_init (mcp23x17_t *dev, gpio_t pin, gpio_mode_t mode) |
Initialize a MCP23x17 pin. More... | |
int | mcp23x17_gpio_init_int (mcp23x17_t *dev, gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t isr, void *arg) |
Initialize a MCP23x17 pin for external interrupt usage. More... | |
int | mcp23x17_gpio_read (mcp23x17_t *dev, gpio_t pin) |
Get the value from MCP23x17 input pin. More... | |
void | mcp23x17_gpio_write (mcp23x17_t *dev, gpio_t pin, int value) |
Write the value to MCP23x17 input pin. More... | |
void | mcp23x17_gpio_clear (mcp23x17_t *dev, gpio_t pin) |
Clear the MCP23x17 output pin. More... | |
void | mcp23x17_gpio_set (mcp23x17_t *dev, gpio_t pin) |
Set the MCP23x17 output pin. More... | |
void | mcp23x17_gpio_toggle (mcp23x17_t *dev, gpio_t pin) |
Toggle the value of the MCP23x17 output pin. More... | |
void | mcp23x17_gpio_irq_enable (mcp23x17_t *dev, gpio_t pin) |
Enable pin interrupt. More... | |
void | mcp23x17_gpio_irq_disable (mcp23x17_t *dev, gpio_t pin) |
Disable pin interrupt. More... | |
#define MCP23X17_BASE_ADDR (0x20) |
MCP23x17 device base address.
The address of a MCP23x17 device, both for devices with I2C interface and for devices with SPI interface, is defined as the offset to a base address. The address is in the range from 0 to 7 and is defined for the respective MCP23x17 device by its hardware address pins A0 ... A2.
Definition at line 379 of file mcp23x17.h.
#define MCP23X17_GPIO_PIN | ( | port, | |
pin | |||
) | ((gpio_t)((port << 3) | pin)) |
Conversion of (port x : pin y) to a pin number.
MCP23x17 expanders have 16 pins arranged in 2 ports with 8 pins each. MCP23X17_GPIO_PIN can either be used
to address the 16 expander pins.
Definition at line 397 of file mcp23x17.h.
Named MCP23x17 driver error codes.
Definition at line 402 of file mcp23x17.h.
enum mcp23x17_if_t |
MCP23x17 interface types.
Enumerator | |
---|---|
MCP23X17_I2C | I2C interface used. |
MCP23X17_SPI | SPI interface used. |
Definition at line 417 of file mcp23x17.h.
void mcp23x17_gpio_clear | ( | mcp23x17_t * | dev, |
gpio_t | pin | ||
) |
Clear the MCP23x17 output pin.
[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | pin | pin to clear, use MCP23X17_GPIO_PIN(x,y) to specify |
int mcp23x17_gpio_init | ( | mcp23x17_t * | dev, |
gpio_t | pin, | ||
gpio_mode_t | mode | ||
) |
Initialize a MCP23x17 pin.
[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | pin | Pin to initialize, use MCP23X17_GPIO_PIN(x,y) to specify |
[in] | mode | Mode of the pin, see gpio_t |
MCP23X17_OK | on success |
MCP23X17_ERROR_* | on error, a negative error code, see mcp23x17_error_codes_t |
int mcp23x17_gpio_init_int | ( | mcp23x17_t * | dev, |
gpio_t | pin, | ||
gpio_mode_t | mode, | ||
gpio_flank_t | flank, | ||
gpio_cb_t | isr, | ||
void * | arg | ||
) |
Initialize a MCP23x17 pin for external interrupt usage.
The registered callback function will be called in interrupt context every time the defined flank(s) are detected. Therefore, it MUST NOT be blocking or time-consuming.
The interrupt is activated automatically after the initialization.
mcp23x17_irq
has to be added to the project to enable this function.INTA
/INTB
signal has to be defined by parameter mcp23x17_params_t::int_pin.[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | pin | pin to initialize, use MCP23X17_GPIO_PIN(x,y) to specify |
[in] | mode | mode of the pin, see gpio_t |
[in] | flank | define the active flanks, see gpio_flank_t |
[in] | isr | ISR that is called back from interrupt context |
[in] | arg | optional argument passed to the callback |
MCP23X17_OK | on success |
MCP23X17_ERROR_* | on error, a negative error code, see mcp23x17_error_codes_t |
void mcp23x17_gpio_irq_disable | ( | mcp23x17_t * | dev, |
gpio_t | pin | ||
) |
Disable pin interrupt.
mcp23x17_irq
has to be added to the project to enable this function.INTA
/INTB
signal has to be defined by parameter mcp23x17_params_t::int_pin.[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | pin | pin to enable the interrupt for |
void mcp23x17_gpio_irq_enable | ( | mcp23x17_t * | dev, |
gpio_t | pin | ||
) |
Enable pin interrupt.
mcp23x17_irq
has to be added to the project to enable this function.INTA
/INTB
signal has to be defined by parameter mcp23x17_params_t::int_pin.[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | pin | pin to enable the interrupt for |
int mcp23x17_gpio_read | ( | mcp23x17_t * | dev, |
gpio_t | pin | ||
) |
Get the value from MCP23x17 input pin.
[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | pin | pin to read, use MCP23X17_GPIO_PIN(x,y) to specify |
0 | on LOW signal |
1 | on HIGH signal |
MCP23X17_ERROR_* | on error, a negative error code, see mcp23x17_error_codes_t |
void mcp23x17_gpio_set | ( | mcp23x17_t * | dev, |
gpio_t | pin | ||
) |
Set the MCP23x17 output pin.
[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | pin | pin to set, use MCP23X17_GPIO_PIN(x,y) to specify |
void mcp23x17_gpio_toggle | ( | mcp23x17_t * | dev, |
gpio_t | pin | ||
) |
Toggle the value of the MCP23x17 output pin.
[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | pin | pin to toggle, use MCP23X17_GPIO_PIN(x,y) to specify |
void mcp23x17_gpio_write | ( | mcp23x17_t * | dev, |
gpio_t | pin, | ||
int | value | ||
) |
Write the value to MCP23x17 input pin.
[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | pin | pin to write, use MCP23X17_GPIO_PIN(x,y) to specify |
[in] | value | value to write |
int mcp23x17_init | ( | mcp23x17_t * | dev, |
const mcp23x17_params_t * | params | ||
) |
Initialize the MCP23x17 I/O expander.
All expander pins are set to be input and are pulled up.
[in] | dev | Descriptor of MCP23x17 I/O expander device |
[in] | params | Configuration parameters, see mcp23x17_params_t |
MCP23X17_OK | on success |
MCP23X17_ERROR_* | on error, a negative error code, see mcp23x17_error_codes_t |