2022-01-07 14:23:20 -05:00
|
|
|
|
|
|
|
[![Arduino CI](https://github.com/RobTillaart/MCP23S17/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
|
|
|
|
[![Arduino-lint](https://github.com/RobTillaart/MCP23S17/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/MCP23S17/actions/workflows/arduino-lint.yml)
|
|
|
|
[![JSON check](https://github.com/RobTillaart/MCP23S17/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/MCP23S17/actions/workflows/jsoncheck.yml)
|
|
|
|
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/MCP23S17/blob/master/LICENSE)
|
|
|
|
[![GitHub release](https://img.shields.io/github/release/RobTillaart/MCP23S17.svg?maxAge=3600)](https://github.com/RobTillaart/MCP23S17/releases)
|
|
|
|
|
|
|
|
|
|
|
|
# MCP23S17
|
|
|
|
|
|
|
|
Arduino library for MCP23S17 16 channel SPI port expander.
|
|
|
|
|
|
|
|
|
|
|
|
## Description
|
|
|
|
|
|
|
|
This experimental library gives easy control over the 16 pins of a (SPI) MCP23S17 chip.
|
|
|
|
|
2022-01-10 06:58:20 -05:00
|
|
|
This IC is strongly related to the MCP23017 I2C port expander - https://github.com/RobTillaart/MCP23017_RT
|
2022-01-07 14:23:20 -05:00
|
|
|
Programming Interface is kept the same as much as possible.
|
|
|
|
|
|
|
|
|
|
|
|
## Interface
|
|
|
|
|
|
|
|
### Constructor
|
|
|
|
|
2022-07-01 06:10:38 -04:00
|
|
|
- **MCP23S17(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address = 0x00)** constructor SW SPI.
|
|
|
|
- **MCP23S17(uint8_t select, SPIClass\* spi)** constructor HW SPI with explicit SPI interface selected.
|
|
|
|
- **MCP23S17(uint8_t select, uint8_t address = 0x00, SPIClass\* spi = &SPI)** constructor HW SPI with optional address pins and SPI interface.
|
2022-01-07 14:23:20 -05:00
|
|
|
- **bool begin()** returns true if successful.
|
2022-07-01 06:10:38 -04:00
|
|
|
- **bool isConnected()** returns true if connected, false otherwise. (dummy for compatibility reasons)
|
|
|
|
- **uint8_t getAddress()** returns the address set in the constructor.
|
|
|
|
Default = 0, range = 0..7.
|
|
|
|
|
|
|
|
The two constructors allow to call 4 different constructors.
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
- MCP23S17(10); // select pin only
|
|
|
|
- MCP23S17(10, 7); // select pin + address pins
|
|
|
|
- MCP23S17(10, 7, &SPI2); // select pin + address pins + SPI port
|
|
|
|
- MCP23S17(10, &SPI2); // select pin + SPI port
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### sharing select lines
|
|
|
|
|
|
|
|
(not tested)
|
|
|
|
Technically two chips could use the same select pin and a different address.
|
|
|
|
The constructors would allow to setup such a configuration.
|
|
|
|
I assume that this is less used and IMHO not recommended.
|
2022-01-07 14:23:20 -05:00
|
|
|
|
|
|
|
|
|
|
|
### Single pin interface
|
|
|
|
|
2022-09-28 06:56:28 -04:00
|
|
|
- **bool pinMode(uint8_t pin, uint8_t mode)** pin = 0..15, mode = INPUT, OUTPUT. Returns true if successful.
|
|
|
|
- **bool digitalWrite(uint8_t pin, uint8_t value)** pin = 0..15, value = LOW(0) HIGH (!0). Returns true if successful.
|
2022-01-07 14:23:20 -05:00
|
|
|
- **uint8_t digitalRead(uint8_t pin)** pin = 0..15, returns LOW or HIGH, might set the lastError();
|
2022-09-28 06:56:28 -04:00
|
|
|
- **bool setPolarity(uint8_t pin, bool reversed)** pin = 0..15, set reversed flag. Returns true if successful.
|
|
|
|
- **bool getPolarity(uint8_t pin, bool &reversed)** pin = 0..15, reads reversed flag. Returns true if successful.
|
|
|
|
- **bool setPullup(uint8_t pin, bool pullup)** pin = 0..15, set pull-up flag. Returns true if successful.
|
|
|
|
- **bool getPullup(uint8_t pin, bool &pullup)** pin = 0..15, reads pull-up flag. Returns true if successful.
|
2022-01-07 14:23:20 -05:00
|
|
|
|
|
|
|
|
|
|
|
### 8 pins interface
|
|
|
|
|
2022-09-28 06:56:28 -04:00
|
|
|
- **bool pinMode8(uint8_t port, uint8_t value)** port = 0..1, value = 0..255. Returns true if successful.
|
|
|
|
- **bool write8(uint8_t port, uint8_t value)** port = 0..1, value = 0..255. Returns true if successful.
|
2022-01-07 14:23:20 -05:00
|
|
|
- **uint8_t read8(uint8_t port)** port = 0..1, reads 8 pins into one byte.
|
|
|
|
- **bool setPolarity8(uint8_t port, uint8_t mask)** port = 0..1, sets polarity for 8 channels at once.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-07 14:23:20 -05:00
|
|
|
- **bool getPolarity8(uint8_t port, uint8_t &mask)** port = 0..1, reads polarity of 8 channels at once.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-10 06:58:20 -05:00
|
|
|
- **bool setPullup8(uint8_t port, uint8_t mask)** port = 0..1, sets pull-up for 8 channels at once.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-07 14:23:20 -05:00
|
|
|
- **bool getPullup8(uint8_t port, uint8_t &mask)** port = 0..1, reads pull-up for 8 channels at once.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-07 14:23:20 -05:00
|
|
|
|
|
|
|
|
2022-01-10 06:58:20 -05:00
|
|
|
### 16 pins interface
|
|
|
|
|
|
|
|
- **bool pinMode16(uint16_t value)** value = 0..0xFFFF, returns true if successful.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-10 06:58:20 -05:00
|
|
|
- **bool write16(uint16_t value)** value = 0..0xFFFF, returns true if successful.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-10 06:58:20 -05:00
|
|
|
- **uint16_t read16()** reads 16 pins into an uint16_t.
|
|
|
|
- **bool setPolarity16(uint16_t mask)** sets polarity for 16 channels.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-10 06:58:20 -05:00
|
|
|
- **bool getPolarity16(uint16_t &mask)** reads polarity of 16 channels.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-10 06:58:20 -05:00
|
|
|
- **bool setPullup16(uint16_t mask)** sets pull-up for 16 channels.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-10 06:58:20 -05:00
|
|
|
- **bool getPullup16(uint16_t &mask)** reads pull-up for 16 channels.
|
2022-09-28 06:56:28 -04:00
|
|
|
Returns true if successful.
|
2022-01-10 06:58:20 -05:00
|
|
|
|
|
|
|
|
2022-10-24 05:13:46 -04:00
|
|
|
### IO Control Register
|
|
|
|
|
|
|
|
Since 0.2.3 the library supports setting bit fields in the IO control register.
|
|
|
|
Read the datasheet carefully!
|
|
|
|
|
|
|
|
- **void enableControlRegister(uint8_t mask)**
|
|
|
|
- **void disableControlRegister(uint8_t mask)**
|
|
|
|
|
|
|
|
|
|
|
|
| constant | mask | description |
|
|
|
|
|:-----------------------|:------:|:--------------|
|
|
|
|
| MCP23S17_IOCR_BANK | 0x80 | Controls how the registers are addressed.
|
|
|
|
| MCP23S17_IOCR_MIRROR | 0x40 | INT Pins Mirror bit.
|
|
|
|
| MCP23S17_IOCR_SEQOP | 0x20 | Sequential Operation mode bit.
|
|
|
|
| MCP23S17_IOCR_DISSLW | 0x10 | Slew Rate control bit for SDA output.
|
|
|
|
| MCP23S17_IOCR_HAEN | 0x08 | Hardware Address Enable bit (MCP23S17 only).
|
|
|
|
| MCP23S17_IOCR_ODR | 0x04 | Configures the INT pin as an open-drain output.
|
|
|
|
| MCP23S17_IOCR_INTPOL | 0x02 | This bit sets the polarity of the INT output pin.
|
|
|
|
| MCP23S17_IOCR_NI | 0x01 | Not implemented.
|
|
|
|
|
2022-01-07 14:23:20 -05:00
|
|
|
### Error codes
|
|
|
|
|
2022-09-28 06:56:28 -04:00
|
|
|
If one of the above functions return false, there might be an error.
|
|
|
|
|
2022-01-07 14:23:20 -05:00
|
|
|
- **int lastError()** Above functions set an error flag that can be read with this function.
|
|
|
|
Reading it will reset the flag to **MCP23S17_OK**.
|
|
|
|
|
2022-07-01 06:10:38 -04:00
|
|
|
| NAME | VALUE | DESCRIPTION |
|
|
|
|
|:------------------------|:------:|:------------|
|
|
|
|
| MCP23S17_OK | 0x00 | No error |
|
|
|
|
| MCP23S17_PIN_ERROR | 0x81 |
|
|
|
|
| MCP23S17_I2C_ERROR | 0x82 | (compatibility)
|
|
|
|
| MCP23S17_VALUE_ERROR | 0x83 |
|
|
|
|
| MCP23S17_PORT_ERROR | 0x84 |
|
|
|
|
| MCP23S17_REGISTER_ERROR | 0xFF | low level.
|
2022-01-07 14:23:20 -05:00
|
|
|
|
|
|
|
|
|
|
|
## Operation
|
|
|
|
|
|
|
|
See examples.
|
|
|
|
|
|
|
|
|
|
|
|
## Future
|
|
|
|
|
2022-10-24 05:13:46 -04:00
|
|
|
#### must
|
|
|
|
|
2022-07-01 06:10:38 -04:00
|
|
|
- improve documentation
|
2022-10-24 05:13:46 -04:00
|
|
|
- references to I2C version?
|
|
|
|
|
|
|
|
#### should
|
|
|
|
|
2022-01-07 14:23:20 -05:00
|
|
|
- keep functional in sync with MCP23017_RT
|
2022-10-24 05:13:46 -04:00
|
|
|
|
|
|
|
#### could
|
|
|
|
|
|
|
|
- check need for writing in all functions (Polarity / pullup)
|
|
|
|
- check if bit mask changes.
|
|
|
|
- what is performance gain vs footprint?
|
2022-07-01 06:10:38 -04:00
|
|
|
- implement ESP32 specific support in begin()
|
|
|
|
- see MCP_ADC.begin()
|
|
|
|
- SW_SPI is roughly equal in performance as HW SPI on ESP32.
|
|
|
|
- investigate and reimplement the INPUT_PULLUP for pinMode() ?
|
|
|
|
|
|
|
|
#### wont
|
|
|
|
|
|
|
|
- check address range in constructor.
|
|
|
|
|
2022-04-14 04:53:15 -04:00
|
|
|
|