0.3.1 MCP23017_RT

This commit is contained in:
rob tillaart 2022-09-28 11:19:03 +02:00
parent 56b01d1fcd
commit 3d573a8dcd
7 changed files with 240 additions and 63 deletions

View File

@ -22,6 +22,7 @@
// update register defines
//
// 0.3.0 2022-06-28 fix incorrect masking - see #10 MCP23S17
// 0.3.1 2022-09-28 optimize digitalWrite() - most used one only.
#include "MCP23017.h"
@ -65,11 +66,11 @@ bool MCP23017::begin(const uint8_t dataPin, const uint8_t clockPin)
{
_wire = &Wire;
_wire->begin(dataPin, clockPin);
// check connected
// check connected
if (! isConnected()) return false;
// disable address increment (datasheet)
// disable address increment (datasheet)
if (! writeReg(MCP23017_IOCR, 0b00100000)) return false;
// Force INPUT_PULLUP
// Force INPUT_PULLUP
if (! writeReg(MCP23017_PUR_A, 0xFF)) return false;
if (! writeReg(MCP23017_PUR_B, 0xFF)) return false;
return true;
@ -80,11 +81,11 @@ bool MCP23017::begin(const uint8_t dataPin, const uint8_t clockPin)
bool MCP23017::begin()
{
_wire->begin();
// check connected
// check connected
if (! isConnected()) return false;
// disable address increment (datasheet)
// disable address increment (datasheet)
if (! writeReg(MCP23017_IOCR, 0b00100000)) return false;
// Force INPUT_PULLUP
// Force INPUT_PULLUP
if (! writeReg(MCP23017_PUR_A, 0xFF)) return false;
if (! writeReg(MCP23017_PUR_B, 0xFF)) return false;
return true;
@ -104,9 +105,9 @@ bool MCP23017::isConnected()
}
// 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 MCP23017::pinMode(uint8_t pin, uint8_t mode)
{
if (pin > 15)
@ -132,7 +133,7 @@ bool MCP23017::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;
@ -141,7 +142,7 @@ bool MCP23017::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 != MCP23017_OK)
{
@ -151,8 +152,8 @@ bool MCP23017::pinMode(uint8_t pin, uint8_t mode)
}
// pin = 0..15
// value = LOW, HIGH
// pin = 0..15
// value = LOW, HIGH
bool MCP23017::digitalWrite(uint8_t pin, uint8_t value)
{
if (pin > 15)
@ -168,6 +169,7 @@ bool MCP23017::digitalWrite(uint8_t pin, uint8_t value)
}
uint8_t val = readReg(IOR);
uint8_t pre = val;
if (_error != MCP23017_OK)
{
return false;
@ -182,10 +184,13 @@ bool MCP23017::digitalWrite(uint8_t pin, uint8_t value)
{
val &= ~mask;
}
writeReg(IOR, val);
if (_error != MCP23017_OK)
if (pre != val)
{
return false;
writeReg(IOR, val);
if (_error != MCP23017_OK)
{
return false;
}
}
return true;
}
@ -216,8 +221,8 @@ uint8_t MCP23017::digitalRead(uint8_t pin)
}
// pin = 0..15
// reverse = true or false
// pin = 0..15
// reverse = true or false
bool MCP23017::setPolarity(uint8_t pin, bool reversed)
{
if (pin > 15)
@ -278,8 +283,8 @@ bool MCP23017::getPolarity(uint8_t pin, bool &reversed)
}
// pin = 0..15
// reverse = true or false
// pin = 0..15
// reverse = true or false
bool MCP23017::setPullup(uint8_t pin, bool pullup)
{
if (pin > 15)
@ -341,9 +346,10 @@ bool MCP23017::getPullup(uint8_t pin, bool &pullup)
///////////////////////////////////////////////////////////////////////
// 8 pins interface
// whole register at once
// port = 0..1
//
// 8 pins interface
// whole register at once
// port = 0..1
// value = 0..0xFF bit pattern
bool MCP23017::pinMode8(uint8_t port, uint8_t value)
{
@ -386,8 +392,8 @@ int MCP23017::read8(uint8_t port)
}
// port = 0..1
// mask = 0..0xFF bit pattern
// port = 0..1
// mask = 0..0xFF bit pattern
bool MCP23017::setPolarity8(uint8_t port, uint8_t mask)
{
if (port > 1)
@ -422,8 +428,8 @@ bool MCP23017::getPolarity8(uint8_t port, uint8_t &mask)
}
// port = 0..1
// mask = 0..0xFF bit pattern
// port = 0..1
// mask = 0..0xFF bit pattern
bool MCP23017::setPullup8(uint8_t port, uint8_t mask)
{
if (port > 1)
@ -459,9 +465,10 @@ bool MCP23017::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 MCP23017::pinMode16(uint16_t value)
{
writeReg(MCP23017_DDR_A, value >> 8);
@ -471,7 +478,7 @@ bool MCP23017::pinMode16(uint16_t value)
}
// value = 0..0xFFFF bit pattern
// value = 0x0000..0xFFFF bit pattern
bool MCP23017::write16(uint16_t value)
{
writeReg(MCP23017_GPIO_A, value >> 8);
@ -481,7 +488,7 @@ bool MCP23017::write16(uint16_t value)
}
// return = 0..0xFFFF bit pattern
// return = 0x0000..0xFFFF bit pattern
uint16_t MCP23017::read16()
{
_error = MCP23017_OK;
@ -492,7 +499,7 @@ uint16_t MCP23017::read16()
}
// mask = 0..0xFFFF bit pattern
// mask = 0x0000..0xFFFF bit pattern
bool MCP23017::setPolarity16(uint16_t mask)
{
writeReg(MCP23017_POL_A, mask >> 8);
@ -505,7 +512,7 @@ bool MCP23017::setPolarity16(uint16_t mask)
}
// mask = 0..0xFFFF bit pattern
// mask = 0x0000..0xFFFF bit pattern
bool MCP23017::getPolarity16(uint16_t &mask)
{
mask = readReg(MCP23017_POL_A);
@ -519,7 +526,7 @@ bool MCP23017::getPolarity16(uint16_t &mask)
}
// mask = 0..0xFFFF bit pattern
// mask = 0x0000..0xFFFF bit pattern
bool MCP23017::setPullup16(uint16_t mask)
{
writeReg(MCP23017_PUR_A, mask >> 8);
@ -532,7 +539,7 @@ bool MCP23017::setPullup16(uint16_t mask)
}
// mask = 0..0xFFFF bit pattern
// mask = 0x0000..0xFFFF bit pattern
bool MCP23017::getPullup16(uint16_t &mask)
{
mask = readReg(MCP23017_PUR_A);
@ -549,7 +556,7 @@ bool MCP23017::getPullup16(uint16_t &mask)
int MCP23017::lastError()
{
int e = _error;
_error = MCP23017_OK; // reset error after read.
_error = MCP23017_OK; // reset error after read.
return e;
}
@ -598,3 +605,4 @@ uint8_t MCP23017::readReg(uint8_t reg)
// -- END OF FILE --

View File

@ -2,7 +2,7 @@
//
// FILE: MCP23017.h
// AUTHOR: Rob Tillaart
// VERSION: 0.3.0
// VERSION: 0.3.1
// PURPOSE: Arduino library for I2C MCP23017 16 channel port expander
// DATE: 2019-10-12
// URL: https://github.com/RobTillaart/MCP23017_RT
@ -12,7 +12,7 @@
#include "Wire.h"
#define MCP23017_LIB_VERSION (F("0.3.0"))
#define MCP23017_LIB_VERSION (F("0.3.1"))
#define MCP23017_OK 0x00
#define MCP23017_PIN_ERROR 0x81
@ -36,8 +36,8 @@ public:
bool isConnected();
// 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);
@ -48,9 +48,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);
@ -61,8 +61,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();

View File

@ -18,6 +18,9 @@ This library gives easy control over the 16 pins of a (I2C) MCP23017 chip.
This IC is strongly related tot the MCP23S17 SPI port expander - https://github.com/RobTillaart/MCP23S17
Programming Interface is kept the same as much as possible.
Since 0.3.1 the **digitalWrite(pin, value)** is optimized.
If a pin is not changed it will not be written again to save time.
## Interface
@ -32,39 +35,50 @@ Can be overruled with Wire0..WireN.
### 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.
- **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.
- **bool write16(uint16_t value)** value = 0..0xFFFF, returns true if successful.
- **bool pinMode16(uint16_t value)** value = 0..0xFFFF. Returns true if successful.
- **bool write16(uint16_t value)** value = 0..0xFFFF. 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 **MCP23017_OK**.
@ -95,7 +109,6 @@ See examples.
- extend error codes
- optimize code - squeeze footprint
- optimize code - do not write if pin does not chance (~25%)
#### Could

View File

@ -8,8 +8,8 @@
#include "MCP23017.h"
#include "Wire.h"
// MCP23017 MCP(10, 12, 11, 13); // SW SPI address 0x00
MCP23017 MCP(10); // HW SPI address 0x00
// MCP23017 MCP(10, 12, 11, 13); // SW SPI address
MCP23017 MCP(10); // HW SPI address
uint32_t start, stop;
@ -25,6 +25,8 @@ void setup()
Wire.begin();
bool b = MCP.begin();
Serial.print("BEGIN: ");
Serial.println(b);
MCP.pinMode8(0, 0x00); // 0 = output , 1 = input
MCP.pinMode8(1, 0x00);
@ -58,12 +60,14 @@ void setup()
Serial.print("TEST digitalRead(pin):\t");
delay(100);
start = micros();
volatile int val = 0;
for (int pin = 0; pin < 16; pin++)
{
volatile int val = MCP.digitalRead(pin);
val = MCP.digitalRead(pin);
}
stop = micros();
Serial.println((stop - start) / 16.0);
Serial.println(val); // keep build CI compiler happy
Serial.println();
@ -87,6 +91,7 @@ void setup()
val8 = MCP.read8(1);
stop = micros();
Serial.println((stop - start) / 2.0);
Serial.println(val8); // keep build CI compiler happy
Serial.println();
@ -108,6 +113,7 @@ void setup()
volatile uint16_t val16 = MCP.read16();
stop = micros();
Serial.println((stop - start) / 2.0);
Serial.println(val16); // keep build CI compiler happy
Serial.println();
Serial.println("\ndone...");

View File

@ -0,0 +1,150 @@
//
// FILE: MCP23017_test.ino
// AUTHOR: Rob Tillaart
// DATE: 2022-06-28
// PUPROSE: test MCP23017 library
#include "MCP23017.h"
#include "Wire.h"
MCP23017 MCP(0x27);
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("MCP23017_LIB_VERSION: ");
Serial.println(MCP23017_LIB_VERSION);
Serial.println();
delay(100);
Wire.begin();
bool b = MCP.begin();
Serial.println(b ? "true" : "false");
MCP.pinMode8(0, 0x00); // 0 = output , 1 = input
MCP.pinMode8(1, 0x00);
//////////////////////////////////////////////////////////////
//
// test 8 bit interface
//
Serial.println("TEST digitalWrite8(port, value)");
for (uint16_t i = 0; i < 256; i++)
{
MCP.write8(0, i);
MCP.write8(1, i);
uint8_t mask0 = MCP.read8(0);
uint8_t mask1 = MCP.read8(1);
if ((mask0 != i) || (mask1 != i))
{
Serial.print(i);
Serial.print("\t");
Serial.print(MCP.read8(0));
Serial.print("\t");
Serial.print(MCP.read8(1));
Serial.println();
}
}
Serial.println("TEST setPullup8(port, value)");
for (uint16_t i = 0; i < 256; i++)
{
MCP.setPullup8(0, i);
MCP.setPullup8(1, i);
uint8_t mask0, mask1;
MCP.getPullup8(0, mask0);
MCP.getPullup8(1, mask1);
if ((mask0 != i) || (mask1 != i))
{
Serial.print(i);
Serial.print("\t");
Serial.print(mask0);
Serial.print("\t");
Serial.print(mask1);
Serial.println();
}
}
Serial.println("TEST setPolarity8(port, value)");
for (uint16_t i = 0; i < 256; i++)
{
MCP.setPolarity8(0, i);
MCP.setPolarity8(1, i);
uint8_t mask0, mask1;
MCP.getPolarity8(0, mask0);
MCP.getPolarity8(1, mask1);
if ((mask0 != i) || (mask1 != i))
{
Serial.print(i);
Serial.print("\t");
Serial.print(mask0);
Serial.print("\t");
Serial.print(mask1);
Serial.println();
}
}
//////////////////////////////////////////////////////////////
//
// test 16 bit interface
//
Serial.println("TEST digitalWrite16(value)");
for (uint32_t i = 0; i < 65535; i++)
{
MCP.write16(i);
if (MCP.read16() != i)
{
Serial.print(i);
Serial.print("\t");
Serial.print(MCP.read16());
Serial.println();
}
}
Serial.println("TEST setPullup16(value)");
for (uint32_t i = 0; i < 65535; i++)
{
MCP.setPullup16(i);
uint16_t mask = 0;
MCP.getPullup16(mask);
if (mask != i)
{
Serial.print(i);
Serial.print("\t");
Serial.print(mask);
Serial.println();
}
}
Serial.println("TEST setPolarity16(value)");
for (uint32_t i = 0; i < 65535; i++)
{
MCP.setPolarity16(i);
uint16_t mask = 0;
MCP.getPolarity16(mask);
if (mask != i)
{
Serial.print(i);
Serial.print("\t");
Serial.print(mask);
Serial.println();
}
}
}
void loop()
{
}
// -- END OF FILE --

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/MCP23017_RT.git"
},
"version": "0.3.0",
"version": "0.3.1",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=MCP23017_RT
version=0.3.0
version=0.3.1
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for I2C MCP23017 16 channel port expander 16 IO-lines