mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.2.2 MCP23S17
This commit is contained in:
parent
3d573a8dcd
commit
19572c296e
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: MCP23S17.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.1
|
||||
// VERSION: 0.2.2
|
||||
// PURPOSE: Arduino library for SPI MCP23S17 16 channel port expander
|
||||
// DATE: 2021-12-30
|
||||
// URL: https://github.com/RobTillaart/MCP23S17
|
||||
@ -18,6 +18,7 @@
|
||||
// redo constructors.
|
||||
// add getAddress() + optimized (_address << 1)
|
||||
// update readme.md
|
||||
// 0.2.2 2022-09-28 optimize digitalWrite - most used one only.
|
||||
|
||||
|
||||
|
||||
@ -59,7 +60,7 @@
|
||||
#define MCP23S17_IOCR_INTPOL 0x02 // This bit sets the polarity of the INT output pin.
|
||||
#define MCP23S17_IOCR_NI 0x01 // Not implemented.
|
||||
|
||||
// low level read / write masks
|
||||
// low level read / write masks
|
||||
#define MCP23S17_WRITE_REG 0x40
|
||||
#define MCP23S17_READ_REG 0x41
|
||||
|
||||
@ -102,7 +103,7 @@ bool MCP23S17::begin()
|
||||
|
||||
if (_hwSPI)
|
||||
{
|
||||
// _mySPI = &SPI; // set in constructor #10
|
||||
// _mySPI = &SPI; // set in constructor #10
|
||||
_mySPI->end();
|
||||
_mySPI->begin();
|
||||
}
|
||||
@ -115,16 +116,16 @@ bool MCP23S17::begin()
|
||||
::digitalWrite(_clock, LOW);
|
||||
}
|
||||
|
||||
// check connected
|
||||
// check connected
|
||||
if (! isConnected()) return false;
|
||||
|
||||
// disable address increment (datasheet P20
|
||||
// disable address increment (datasheet P20
|
||||
// SEQOP: Sequential Operation mode bit
|
||||
// 1 = Sequential operation disabled, address pointer does not increment.
|
||||
// 0 = Sequential operation enabled, address pointer increments.
|
||||
if (! writeReg(MCP23S17_IOCR, MCP23S17_IOCR_SEQOP)) return false;
|
||||
|
||||
// Force INPUT_PULLUP
|
||||
// Force INPUT_PULLUP
|
||||
if (! writeReg(MCP23S17_PUR_A, 0xFF)) return false; // 0xFF == all UP
|
||||
if (! writeReg(MCP23S17_PUR_B, 0xFF)) return false; // 0xFF == all UP
|
||||
return true;
|
||||
@ -145,9 +146,9 @@ uint8_t MCP23S17::getAddress()
|
||||
}
|
||||
|
||||
|
||||
// single pin interface
|
||||
// pin = 0..15
|
||||
// mode = INPUT, OUTPUT, INPUT_PULLUP (= same as INPUT)
|
||||
// single pin interface
|
||||
// pin = 0..15
|
||||
// mode = INPUT, OUTPUT, INPUT_PULLUP (= same as INPUT)
|
||||
bool MCP23S17::pinMode(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
if (pin > 15)
|
||||
@ -173,7 +174,7 @@ bool MCP23S17::pinMode(uint8_t pin, uint8_t mode)
|
||||
return false;
|
||||
}
|
||||
uint8_t mask = 1 << pin;
|
||||
// only work with valid
|
||||
// only work with valid
|
||||
if ((mode == INPUT) || (mode == INPUT_PULLUP))
|
||||
{
|
||||
val |= mask;
|
||||
@ -182,7 +183,7 @@ bool MCP23S17::pinMode(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
val &= ~mask;
|
||||
}
|
||||
// other values won't change val ....
|
||||
// other values won't change val ....
|
||||
writeReg(dataDirectionRegister, val);
|
||||
if (_error != MCP23S17_OK)
|
||||
{
|
||||
@ -192,8 +193,8 @@ bool MCP23S17::pinMode(uint8_t pin, uint8_t mode)
|
||||
}
|
||||
|
||||
|
||||
// pin = 0..15
|
||||
// value = LOW, HIGH
|
||||
// pin = 0..15
|
||||
// value = LOW, HIGH
|
||||
bool MCP23S17::digitalWrite(uint8_t pin, uint8_t value)
|
||||
{
|
||||
if (pin > 15)
|
||||
@ -209,6 +210,7 @@ bool MCP23S17::digitalWrite(uint8_t pin, uint8_t value)
|
||||
}
|
||||
|
||||
uint8_t val = readReg(IOR);
|
||||
uint8_t pre = val;
|
||||
if (_error != MCP23S17_OK)
|
||||
{
|
||||
return false;
|
||||
@ -223,10 +225,13 @@ bool MCP23S17::digitalWrite(uint8_t pin, uint8_t value)
|
||||
{
|
||||
val &= ~mask;
|
||||
}
|
||||
writeReg(IOR, val);
|
||||
if (_error != MCP23S17_OK)
|
||||
if (pre != val)
|
||||
{
|
||||
return false;
|
||||
writeReg(IOR, val);
|
||||
if (_error != MCP23S17_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -257,8 +262,8 @@ uint8_t MCP23S17::digitalRead(uint8_t pin)
|
||||
}
|
||||
|
||||
|
||||
// pin = 0..15
|
||||
// reversed = true or false
|
||||
// pin = 0..15
|
||||
// reversed = true or false
|
||||
bool MCP23S17::setPolarity(uint8_t pin, bool reversed)
|
||||
{
|
||||
if (pin > 15)
|
||||
@ -319,8 +324,8 @@ bool MCP23S17::getPolarity(uint8_t pin, bool &reversed)
|
||||
}
|
||||
|
||||
|
||||
// pin = 0..15
|
||||
// pullup = true or false
|
||||
// pin = 0..15
|
||||
// pullup = true or false
|
||||
bool MCP23S17::setPullup(uint8_t pin, bool pullup)
|
||||
{
|
||||
if (pin > 15)
|
||||
@ -390,10 +395,11 @@ void MCP23S17::setSPIspeed(uint32_t speed)
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// 8 pins interface
|
||||
// whole register at once
|
||||
// port = 0..1
|
||||
// value = 0..0xFF bit pattern
|
||||
//
|
||||
// 8 pins interface
|
||||
// whole register at once
|
||||
// port = 0..1
|
||||
// value = 0..0xFF bit pattern
|
||||
bool MCP23S17::pinMode8(uint8_t port, uint8_t value)
|
||||
{
|
||||
if (port > 1)
|
||||
@ -408,7 +414,8 @@ bool MCP23S17::pinMode8(uint8_t port, uint8_t value)
|
||||
}
|
||||
|
||||
|
||||
bool MCP23S17::write8(uint8_t port, uint8_t value) // port = 0..1
|
||||
// port = 0..1
|
||||
bool MCP23S17::write8(uint8_t port, uint8_t value)
|
||||
{
|
||||
if (port > 1)
|
||||
{
|
||||
@ -435,8 +442,8 @@ int MCP23S17::read8(uint8_t port)
|
||||
}
|
||||
|
||||
|
||||
// port = 0..1
|
||||
// mask = 0..0xFF bit pattern
|
||||
// port = 0..1
|
||||
// mask = 0..0xFF bit pattern
|
||||
bool MCP23S17::setPolarity8(uint8_t port, uint8_t mask)
|
||||
{
|
||||
if (port > 1)
|
||||
@ -471,8 +478,8 @@ bool MCP23S17::getPolarity8(uint8_t port, uint8_t &mask)
|
||||
}
|
||||
|
||||
|
||||
// port = 0..1
|
||||
// mask = 0..0xFF bit pattern
|
||||
// port = 0..1
|
||||
// mask = 0..0xFF bit pattern
|
||||
bool MCP23S17::setPullup8(uint8_t port, uint8_t mask)
|
||||
{
|
||||
if (port > 1)
|
||||
@ -508,9 +515,10 @@ bool MCP23S17::getPullup8(uint8_t port, uint8_t &mask)
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// 16 pins interface
|
||||
// two register at once
|
||||
// value = 0..0xFFFF bit pattern
|
||||
//
|
||||
// 16 pins interface
|
||||
// two register at once
|
||||
// value = 0x0000..0xFFFF bit pattern
|
||||
bool MCP23S17::pinMode16(uint16_t value)
|
||||
{
|
||||
writeReg(MCP23S17_DDR_A, value >> 8);
|
||||
@ -520,7 +528,7 @@ bool MCP23S17::pinMode16(uint16_t value)
|
||||
}
|
||||
|
||||
|
||||
// value = 0..0xFFFF bit pattern
|
||||
// value = 0x0000..0xFFFF bit pattern
|
||||
bool MCP23S17::write16(uint16_t value)
|
||||
{
|
||||
writeReg(MCP23S17_GPIO_A, value >> 8);
|
||||
@ -530,7 +538,7 @@ bool MCP23S17::write16(uint16_t value)
|
||||
}
|
||||
|
||||
|
||||
// return = 0..0xFFFF bit pattern
|
||||
// return = 0x0000..0xFFFF bit pattern
|
||||
uint16_t MCP23S17::read16()
|
||||
{
|
||||
_error = MCP23S17_OK;
|
||||
@ -541,7 +549,7 @@ uint16_t MCP23S17::read16()
|
||||
}
|
||||
|
||||
|
||||
// mask = 0..0xFFFF bit pattern
|
||||
// mask = 0x0000..0xFFFF bit pattern
|
||||
bool MCP23S17::setPolarity16(uint16_t mask)
|
||||
{
|
||||
writeReg(MCP23S17_POL_A, mask >> 8);
|
||||
@ -554,7 +562,7 @@ bool MCP23S17::setPolarity16(uint16_t mask)
|
||||
}
|
||||
|
||||
|
||||
// mask = 0..0xFFFF bit pattern
|
||||
// mask = 0x0000..0xFFFF bit pattern
|
||||
bool MCP23S17::getPolarity16(uint16_t &mask)
|
||||
{
|
||||
mask = readReg(MCP23S17_POL_A);
|
||||
@ -568,7 +576,7 @@ bool MCP23S17::getPolarity16(uint16_t &mask)
|
||||
}
|
||||
|
||||
|
||||
// mask = 0..0xFFFF bit pattern
|
||||
// mask = 0x0000..0xFFFF bit pattern
|
||||
bool MCP23S17::setPullup16(uint16_t mask)
|
||||
{
|
||||
writeReg(MCP23S17_PUR_A, mask >> 8);
|
||||
@ -581,7 +589,7 @@ bool MCP23S17::setPullup16(uint16_t mask)
|
||||
}
|
||||
|
||||
|
||||
// mask = 0..0xFFFF bit pattern
|
||||
// mask = 0x0000..0xFFFF bit pattern
|
||||
bool MCP23S17::getPullup16(uint16_t &mask)
|
||||
{
|
||||
mask = readReg(MCP23S17_PUR_A);
|
||||
@ -598,14 +606,14 @@ bool MCP23S17::getPullup16(uint16_t &mask)
|
||||
int MCP23S17::lastError()
|
||||
{
|
||||
int e = _error;
|
||||
_error = MCP23S17_OK; // reset error after read.
|
||||
_error = MCP23S17_OK; // reset error after read.
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE
|
||||
// PRIVATE
|
||||
//
|
||||
|
||||
bool MCP23S17::writeReg(uint8_t reg, uint8_t value)
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// FILE: MCP23S17.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.2.1
|
||||
// VERSION: 0.2.2
|
||||
// PURPOSE: Arduino library for SPI MCP23S17 16 channel port expander
|
||||
// DATE: 2021-12-30
|
||||
// URL: https://github.com/RobTillaart/MCP23S17
|
||||
@ -12,7 +12,7 @@
|
||||
#include "SPI.h"
|
||||
|
||||
|
||||
#define MCP23S17_LIB_VERSION (F("0.2.1"))
|
||||
#define MCP23S17_LIB_VERSION (F("0.2.2"))
|
||||
|
||||
#define MCP23S17_OK 0x00
|
||||
#define MCP23S17_PIN_ERROR 0x81
|
||||
@ -44,8 +44,8 @@ public:
|
||||
uint8_t getAddress(); // typically returns 0x00
|
||||
|
||||
|
||||
// single pin interface
|
||||
// mode = INPUT, OUTPUT or INPUT_PULLUP (==INPUT)
|
||||
// single pin interface
|
||||
// mode = INPUT, OUTPUT or INPUT_PULLUP (==INPUT)
|
||||
bool pinMode(uint8_t pin, uint8_t mode);
|
||||
bool digitalWrite(uint8_t pin, uint8_t value);
|
||||
uint8_t digitalRead(uint8_t pin);
|
||||
@ -56,9 +56,9 @@ public:
|
||||
bool getPullup(uint8_t pin, bool &pullup);
|
||||
|
||||
|
||||
// 8 pins interface
|
||||
// port = 0..1
|
||||
// value = bit pattern
|
||||
// 8 pins interface
|
||||
// port = 0..1
|
||||
// value = bit pattern
|
||||
bool pinMode8(uint8_t port, uint8_t value);
|
||||
bool write8(uint8_t port, uint8_t value);
|
||||
int read8(uint8_t port);
|
||||
@ -69,8 +69,8 @@ public:
|
||||
bool getPullup8(uint8_t port, uint8_t &mask);
|
||||
|
||||
|
||||
// 16 pins interface
|
||||
// value = bit pattern
|
||||
// 16 pins interface
|
||||
// value = bit pattern
|
||||
bool pinMode16(uint16_t value);
|
||||
bool write16(uint16_t value);
|
||||
uint16_t read16();
|
||||
@ -85,7 +85,7 @@ public:
|
||||
void setSPIspeed(uint32_t speed);
|
||||
uint32_t getSPIspeed() { return _SPIspeed; };
|
||||
|
||||
// debugging
|
||||
// debugging
|
||||
bool usesHWSPI() { return _hwSPI; };
|
||||
int lastError();
|
||||
|
||||
@ -101,7 +101,7 @@ private:
|
||||
uint8_t _error = MCP23S17_OK;
|
||||
|
||||
bool _hwSPI = true;
|
||||
// 10 MHz is maximum, 8 is a better clock divider
|
||||
// 10 MHz is maximum, 8 is a better clock divider
|
||||
uint32_t _SPIspeed = MCP23S17_TYP_SPI_SPEED;
|
||||
SPIClass * _mySPI;
|
||||
SPISettings _spi_settings;
|
||||
|
@ -51,39 +51,51 @@ I assume that this is less used and IMHO not recommended.
|
||||
|
||||
### Single pin interface
|
||||
|
||||
- **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.
|
||||
- **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.
|
||||
- **uint8_t digitalRead(uint8_t pin)** pin = 0..15, returns LOW or HIGH, might set the lastError();
|
||||
- **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.
|
||||
- **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.
|
||||
|
||||
|
||||
### 8 pins interface
|
||||
|
||||
- **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.
|
||||
- **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.
|
||||
- **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.
|
||||
Returns true if successful.
|
||||
- **bool getPolarity8(uint8_t port, uint8_t &mask)** port = 0..1, reads polarity of 8 channels at once.
|
||||
Returns true if successful.
|
||||
- **bool setPullup8(uint8_t port, uint8_t mask)** port = 0..1, sets pull-up for 8 channels at once.
|
||||
Returns true if successful.
|
||||
- **bool getPullup8(uint8_t port, uint8_t &mask)** port = 0..1, reads pull-up for 8 channels at once.
|
||||
Returns true if successful.
|
||||
|
||||
|
||||
### 16 pins interface
|
||||
|
||||
- **bool pinMode16(uint16_t value)** value = 0..0xFFFF, returns true if successful.
|
||||
Returns true if successful.
|
||||
- **bool write16(uint16_t value)** value = 0..0xFFFF, returns true if successful.
|
||||
Returns true if successful.
|
||||
- **uint16_t read16()** reads 16 pins into an uint16_t.
|
||||
- **bool setPolarity16(uint16_t mask)** sets polarity for 16 channels.
|
||||
Returns true if successful.
|
||||
- **bool getPolarity16(uint16_t &mask)** reads polarity of 16 channels.
|
||||
Returns true if successful.
|
||||
- **bool setPullup16(uint16_t mask)** sets pull-up for 16 channels.
|
||||
Returns true if successful.
|
||||
- **bool getPullup16(uint16_t &mask)** reads pull-up for 16 channels.
|
||||
Returns true if successful.
|
||||
|
||||
|
||||
### Error codes
|
||||
|
||||
If one of the above functions return false, there might be an error.
|
||||
|
||||
- **int lastError()** Above functions set an error flag that can be read with this function.
|
||||
Reading it will reset the flag to **MCP23S17_OK**.
|
||||
|
||||
|
@ -34,6 +34,8 @@ void setup()
|
||||
Serial.print("HWSPI: ");
|
||||
Serial.println(MCP.usesHWSPI());
|
||||
|
||||
MCP.setSPIspeed(10000000);
|
||||
|
||||
MCP.pinMode8(0, 0x00); // 0 = output , 1 = input
|
||||
MCP.pinMode8(1, 0x00);
|
||||
|
||||
@ -97,7 +99,7 @@ void setup()
|
||||
Serial.println((stop - start) / 2.0);
|
||||
Serial.println();
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//
|
||||
// write16 read16 interface
|
||||
|
@ -0,0 +1,35 @@
|
||||
|
||||
|
||||
# Performance test
|
||||
|
||||
Test sketch MCP23S17_performance.ino
|
||||
|
||||
Max clock frequency 10 MHz, for an UNO this is 8 MHz (divider of CPU clock)
|
||||
|
||||
### Library version: 0.2.2
|
||||
|
||||
| Action | SW SPI | HW 1 MHz | HW 2 MHz | HW 4 MHz | HW 8 MHz | notes |
|
||||
|:------------------------------|--------:|---------:|---------:|---------:|---------:|:---------:|
|
||||
| TEST digitalWrite(0, value) | 676.75 | 67.00 | 48.75 | 39.75 | 35.25 | Optimized!
|
||||
| TEST digitalWrite(pin, value) | 678.00 | 68.25 | 50.00 | 41.25 | 36.50 | Optimized!
|
||||
| TEST digitalRead(pin) | 452.00 | 45.00 | 32.50 | 27.25 | 23.75 |
|
||||
| | | | | | |
|
||||
| TEST write8(port, mask) | 450.00 | 44.00 | 32.00 | 26.00 | 24.00 |
|
||||
| TEST read8(port) | 450.00 | 44.00 | 32.00 | 26.00 | 24.00 |
|
||||
| TEST write16(mask) | 452.00 | 48.00 | 32.00 | 26.00 | 22.00 | since 0.1.1
|
||||
| TEST read16() | 452.00 | 44.00 | 32.00 | 26.00 | 22.00 | since 0.1.1
|
||||
|
||||
|
||||
### Notes
|
||||
|
||||
Performance as expected.
|
||||
|
||||
0.2.2 has optimized digitalWrite(pin, value) when value is same as in IO register.
|
||||
|
||||
|
||||
### Future
|
||||
|
||||
- test ESP32 and other platforms
|
||||
- register based IO version for the SW SPI on AVR ?
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/MCP23S17.git"
|
||||
},
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.2",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=MCP23S17
|
||||
version=0.2.1
|
||||
version=0.2.2
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for SPI MCP23S17 16 channel port expander 16 IO-lines
|
||||
|
Loading…
Reference in New Issue
Block a user