Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ This library provides full control over the Microchip's [MCP23017](https://www.m
* Full interrupt support

## Usage
Unlike most Arduino library, no default instance is created when the library is included. It's up to you to create one with the appropriate chip I2C address.
Unlike most Arduino library, no default instance is created when the library is included. It's up to you to create one using the appropriate I2C address based on MCP23017 `A0`, `A1` and `A2` pins wirings.
Available addresses go from `0x20` to `0x27`, allowing up to 8 MCP23017 on the same I2C bus.

```cpp
#include <Arduino.h>
Expand All @@ -23,7 +24,11 @@ MCP23017 mcp = MCP23017(0x24);
Additionaly, you can specify the `Wire` instance to use as a second argument. For instance `MCP23017(0x24, Wire1)`.
See included examples for further usage.

## Remarks
## Warning about GPA7 & GPB7

GPA7 or GPB7 should not be used as inputs despite what the configuration registers allow. As [stated by Microchip](https://microchip.my.site.com/s/article/GPA7---GPB7-Cannot-Be-Used-as-Inputs-In-MCP23017), it can lead to SDA signal corruption or even malfunction in the host bus under some conditions.

## Breaking changes in v2.0.0
Major renames have been performed in v2.0.0 to improve compatibility with a variety of platforms. Existing code *will* break when you update from version v1.x.

| Name in v1.x | Name in v2.x |
Expand All @@ -32,4 +37,4 @@ Major renames have been performed in v2.0.0 to improve compatibility with a vari
| `MCP23017_REGISTER` | `MCP23017Register` |
| `MCP23017_INTMODE` | `MCP23017InterruptMode` |

In addition to this, every member of the `MCP23017Register` enum were renamed to avoid possible conflicts with macro definitions. `GPIOA` was renamed to `GPIO_A`, `INTCAPA` to `INTCAP_A` and so on...
In addition to this, every member of the `MCP23017Register` enum were renamed to avoid possible conflicts with macro definitions. `GPIOA` was renamed to `GPIO_A`, `INTCAPA` to `INTCAP_A` and so on...
6 changes: 3 additions & 3 deletions examples/PortCopy/PortCopy.ino
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* On every loop, the state of the port B is copied to port A.
*
* Use active low inputs on port A. Internal pullups are enabled by default by the library so there is no need for external resistors.
* Place LEDS on port B for instance.
* Use active low inputs on port B. Internal pullups are enabled by default by the library so there is no need for external resistors.
* Place LEDS on port A for instance.
* When pressing a button, the corresponding led is shut down.
*
* You can also uncomment one line to invert the input (when pressing a button the corresponding led is lit)
Expand Down Expand Up @@ -35,4 +35,4 @@ void loop() {

currentB = mcp.readPort(MCP23017Port::B);
mcp.writePort(MCP23017Port::A, currentB);
}
}
22 changes: 19 additions & 3 deletions src/MCP23017.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ MCP23017::MCP23017(uint8_t address, TwoWire& bus) {
_bus = &bus;
}

MCP23017::MCP23017(TwoWire& bus) {
_deviceAddr = MCP23017_I2C_ADDRESS;
_bus = &bus;
}

MCP23017::~MCP23017() {}

void MCP23017::init()
Expand All @@ -14,12 +19,23 @@ void MCP23017::init()
//SEQOP = 1 : sequential operation disabled, address pointer does not increment
//DISSLW = 0 : slew rate enabled
//HAEN = 0 : hardware address pin is always enabled on 23017
//ODR = 0 : open drain output
//ODR = 0 : active driver output (INTPOL bit sets the polarity.)

//INTPOL = 0 : interrupt active low
//UNIMPLMENTED 0 : unimplemented: Read as ‘0’

writeRegister(MCP23017Register::IOCON, 0b00100000);
}

//enable all pull up resistors (will be effective for input pins only)
writeRegister(MCP23017Register::GPPU_A, 0xFF, 0xFF);
void MCP23017::begin()
{
init();
}

void MCP23017::begin(uint8_t address)
{
_deviceAddr = address;
begin();
}

void MCP23017::portMode(MCP23017Port port, uint8_t directions, uint8_t pullups, uint8_t inverted)
Expand Down
43 changes: 40 additions & 3 deletions src/MCP23017.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <Arduino.h>
#include <Wire.h>

#define MCP23017_I2C_ADDRESS 0x20 ///< The default I2C address of MCP23017.
#define _MCP23017_INTERRUPT_SUPPORT_ ///< Enables support for MCP23017 interrupts.

enum class MCP23017Port : uint8_t
Expand All @@ -11,6 +12,28 @@ enum class MCP23017Port : uint8_t
B = 1
};

struct MCP23017Pin
{
enum Names {
GPA0 = 0,
GPA1,
GPA2,
GPA3,
GPA4,
GPA5,
GPA6,
GPA7,
GPB0 = 8,
GPB1,
GPB2,
GPB3,
GPB4,
GPB5,
GPB6,
GPB7
};
};

/**
* Controls if the two interrupt pins mirror each other.
* See "3.6 Interrupt Logic".
Expand Down Expand Up @@ -65,10 +88,24 @@ class MCP23017
* Instantiates a new instance to interact with a MCP23017 at the specified address.
*/
MCP23017(uint8_t address, TwoWire& bus = Wire);
/**
* Instantiates a new instance to interact with a MCP23017 at the
* MCP23017_I2C_ADDRESS default.
*/
MCP23017(TwoWire& bus = Wire);
~MCP23017();
#ifdef _DEBUG
void debug();
#endif
/**
* Uses the I2C address set during construction. Implicitly calls init().
*/
void begin();
/**
* Overrides the I2C address set by the constructor. Implicitly calls begin().

*/
void begin(uint8_t address);
/**
* Initializes the chip with the default configuration.
* Enables Byte mode (IOCON.BANK = 0 and IOCON.SEQOP = 1).
Expand Down Expand Up @@ -191,8 +228,8 @@ class MCP23017

/**
* Controls how the interrupt pins act with each other.
* If intMode is SEPARATED, interrupt conditions on a port will cause its respective INT pin to active.
* If intMode is OR, interrupt pins are OR'ed so an interrupt on one of the port will cause both pints to active.
* If intMode is Separated, interrupt conditions on a port will cause its respective INT pin to active.
* If intMode is Or, interrupt pins are OR'ed so an interrupt on one of the port will cause both pints to active.
*
* Controls the IOCON.MIRROR bit.
* See "3.5.6 Configuration register".
Expand Down Expand Up @@ -221,4 +258,4 @@ class MCP23017
void clearInterrupts(uint8_t& portA, uint8_t& portB);

#endif
};
};