mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.3.3 MCP23008
This commit is contained in:
parent
eff21e95a4
commit
4c9894669e
@ -6,12 +6,20 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.3.3] 2024-05-25
|
||||
- add several interrupt functions (sync MCP23S17)
|
||||
- update **MCP23x08_registers.h** (reuse with MCP23008)
|
||||
- change return type of several functions
|
||||
- e.g **bool enable/disableControlRegister()**
|
||||
- fix support for ARDUINO_ARCH_MBED
|
||||
- update readme.md
|
||||
- update keywords.txt
|
||||
|
||||
## [0.3.2] 2024-03-02
|
||||
- Fix #17, add parameter to **begin(bool pullup)**
|
||||
- remove DATE field from examples as it adds no value.
|
||||
- update GitHub/actions to version v4 in workflows.
|
||||
|
||||
|
||||
## [0.3.1] - 2024-01-05
|
||||
- add URL to examples
|
||||
- minor edits
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// FILE: MCP23008.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.2
|
||||
// VERSION: 0.3.3
|
||||
// PURPOSE: Arduino library for I2C MCP23008 8 channel port expander
|
||||
// DATE: 2019-10-12
|
||||
// URL: https://github.com/RobTillaart/MCP23008
|
||||
@ -10,25 +10,11 @@
|
||||
#include "MCP23008.h"
|
||||
|
||||
|
||||
// Registers // DESCRIPTION DATASHEET
|
||||
#define MCP23008_DDR_A 0x00 // Data Direction Register A P 10
|
||||
#define MCP23008_POL_A 0x01 // Input Polarity A P 11
|
||||
#define MCP23008_GPINTEN_A 0x02 // NOT USED interrupt enable P 12
|
||||
#define MCP23008_DEFVAL_A 0x03 // NOT USED interrupt def P 13
|
||||
#define MCP23008_INTCON_A 0x04 // NOT USED interrupt control P 14
|
||||
#define MCP23008_IOCR 0x05 // IO control register P 15
|
||||
#define MCP23008_PUR_A 0x06 // Pull Up Resistors A P 16
|
||||
#define MCP23008_INTF_A 0x07 // NOT USED interrupt flag P 17
|
||||
#define MCP23008_INTCAP_A 0x08 // NOT USED interrupt capture P 18
|
||||
#define MCP23008_GPIO_A 0x09 // General Purpose IO A P 19
|
||||
#define MCP23008_OLAT_A 0x0A // NOT USED output latch P 20
|
||||
|
||||
|
||||
MCP23008::MCP23008(uint8_t address, TwoWire *wire)
|
||||
{
|
||||
_address = address;
|
||||
_wire = wire;
|
||||
_error = MCP23008_OK;
|
||||
_address = address;
|
||||
_wire = wire;
|
||||
_error = MCP23008_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -36,12 +22,17 @@ bool MCP23008::begin(bool pullup)
|
||||
{
|
||||
// check connected
|
||||
if (! isConnected()) return false;
|
||||
// disable address increment (datasheet)
|
||||
if (! writeReg(MCP23008_IOCR, 0b00100000)) return false;
|
||||
|
||||
// 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(MCP23x08_IOCR, MCP23008_IOCR_SEQOP)) return false;
|
||||
|
||||
if (pullup)
|
||||
{
|
||||
// Force INPUT_PULLUP
|
||||
if (! writeReg(MCP23008_PUR_A, 0xFF)) return false;
|
||||
if (! writeReg(MCP23x08_PUR_A, 0xFF)) return false; // 0xFF == all UP
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -66,7 +57,10 @@ uint8_t MCP23008::getAddress()
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// single pin interface
|
||||
//
|
||||
// pin = 0..7
|
||||
// mode = INPUT, OUTPUT, INPUT_PULLUP (= same as INPUT)
|
||||
bool MCP23008::pinMode1(uint8_t pin, uint8_t mode)
|
||||
@ -82,7 +76,7 @@ bool MCP23008::pinMode1(uint8_t pin, uint8_t mode)
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t dataDirectionRegister = MCP23008_DDR_A;
|
||||
uint8_t dataDirectionRegister = MCP23x08_DDR_A;
|
||||
uint8_t val = readReg(dataDirectionRegister);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
@ -117,7 +111,7 @@ bool MCP23008::write1(uint8_t pin, uint8_t value)
|
||||
_error = MCP23008_PIN_ERROR;
|
||||
return false;
|
||||
}
|
||||
uint8_t IOR = MCP23008_GPIO_A;
|
||||
uint8_t IOR = MCP23x08_GPIO_A;
|
||||
uint8_t val = readReg(IOR);
|
||||
uint8_t pre = val;
|
||||
if (_error != MCP23008_OK)
|
||||
@ -134,8 +128,8 @@ bool MCP23008::write1(uint8_t pin, uint8_t value)
|
||||
{
|
||||
val &= ~mask;
|
||||
}
|
||||
// only write if there is a change
|
||||
if (val != pre)
|
||||
// only write when changed.
|
||||
if (pre != val)
|
||||
{
|
||||
writeReg(IOR, val);
|
||||
if (_error != MCP23008_OK)
|
||||
@ -154,7 +148,7 @@ uint8_t MCP23008::read1(uint8_t pin)
|
||||
_error = MCP23008_PIN_ERROR;
|
||||
return MCP23008_INVALID_READ;
|
||||
}
|
||||
uint8_t IOR = MCP23008_GPIO_A;
|
||||
uint8_t IOR = MCP23x08_GPIO_A;
|
||||
uint8_t val = readReg(IOR);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
@ -166,8 +160,8 @@ uint8_t MCP23008::read1(uint8_t pin)
|
||||
}
|
||||
|
||||
|
||||
// pin = 0..7
|
||||
// reverse = true or false
|
||||
// pin = 0..7
|
||||
// reversed = true or false
|
||||
bool MCP23008::setPolarity(uint8_t pin, bool reversed)
|
||||
{
|
||||
if (pin > 7)
|
||||
@ -175,7 +169,7 @@ bool MCP23008::setPolarity(uint8_t pin, bool reversed)
|
||||
_error = MCP23008_PIN_ERROR;
|
||||
return false;
|
||||
}
|
||||
uint8_t inputPolarityRegister = MCP23008_POL_A;
|
||||
uint8_t inputPolarityRegister = MCP23x08_POL_A;
|
||||
uint8_t val = readReg(inputPolarityRegister);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
@ -206,7 +200,7 @@ bool MCP23008::getPolarity(uint8_t pin, bool &reversed)
|
||||
_error = MCP23008_PIN_ERROR;
|
||||
return false;
|
||||
}
|
||||
uint8_t inputPolarityRegister = MCP23008_POL_A;
|
||||
uint8_t inputPolarityRegister = MCP23x08_POL_A;
|
||||
uint8_t val = readReg(inputPolarityRegister);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
@ -218,8 +212,8 @@ bool MCP23008::getPolarity(uint8_t pin, bool &reversed)
|
||||
}
|
||||
|
||||
|
||||
// pin = 0..7
|
||||
// reverse = true or false
|
||||
// pin = 0..7
|
||||
// pullup = true or false
|
||||
bool MCP23008::setPullup(uint8_t pin, bool pullup)
|
||||
{
|
||||
if (pin > 7)
|
||||
@ -227,7 +221,7 @@ bool MCP23008::setPullup(uint8_t pin, bool pullup)
|
||||
_error = MCP23008_PIN_ERROR;
|
||||
return false;
|
||||
}
|
||||
uint8_t inputPullupRegister = MCP23008_PUR_A;
|
||||
uint8_t inputPullupRegister = MCP23x08_PUR_A;
|
||||
uint8_t val = readReg(inputPullupRegister);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
@ -258,7 +252,7 @@ bool MCP23008::getPullup(uint8_t pin, bool &pullup)
|
||||
_error = MCP23008_PIN_ERROR;
|
||||
return false;
|
||||
}
|
||||
uint8_t inputPullupRegister = MCP23008_PUR_A;
|
||||
uint8_t inputPullupRegister = MCP23x08_PUR_A;
|
||||
uint8_t val = readReg(inputPullupRegister);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
@ -270,14 +264,15 @@ bool MCP23008::getPullup(uint8_t pin, bool &pullup)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 8 pins interface
|
||||
//
|
||||
// whole register at once
|
||||
// value = 0..0xFF bit pattern
|
||||
bool MCP23008::pinMode8(uint8_t value)
|
||||
{
|
||||
writeReg(MCP23008_DDR_A, value);
|
||||
writeReg(MCP23x08_DDR_A, value);
|
||||
_error = MCP23008_OK;
|
||||
return true;
|
||||
}
|
||||
@ -285,7 +280,7 @@ bool MCP23008::pinMode8(uint8_t value)
|
||||
|
||||
bool MCP23008::write8(uint8_t value)
|
||||
{
|
||||
writeReg(MCP23008_GPIO_A, value);
|
||||
writeReg(MCP23x08_GPIO_A, value);
|
||||
_error = MCP23008_OK;
|
||||
return true;
|
||||
}
|
||||
@ -294,14 +289,14 @@ bool MCP23008::write8(uint8_t value)
|
||||
int MCP23008::read8()
|
||||
{
|
||||
_error = MCP23008_OK;
|
||||
return readReg(MCP23008_GPIO_A);
|
||||
return readReg(MCP23x08_GPIO_A);
|
||||
}
|
||||
|
||||
|
||||
// mask = 0..0xFF bit pattern
|
||||
bool MCP23008::setPolarity8(uint8_t mask)
|
||||
{
|
||||
writeReg(MCP23008_POL_A, mask);
|
||||
writeReg(MCP23x08_POL_A, mask);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
return false;
|
||||
@ -312,7 +307,7 @@ bool MCP23008::setPolarity8(uint8_t mask)
|
||||
|
||||
bool MCP23008::getPolarity8(uint8_t &mask)
|
||||
{
|
||||
mask = readReg(MCP23008_POL_A);
|
||||
mask = readReg(MCP23x08_POL_A);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
return false;
|
||||
@ -324,7 +319,7 @@ bool MCP23008::getPolarity8(uint8_t &mask)
|
||||
// mask = 0..0xFF bit pattern
|
||||
bool MCP23008::setPullup8(uint8_t mask)
|
||||
{
|
||||
writeReg(MCP23008_PUR_A, mask);
|
||||
writeReg(MCP23x08_PUR_A, mask);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
return false;
|
||||
@ -335,7 +330,7 @@ bool MCP23008::setPullup8(uint8_t mask)
|
||||
|
||||
bool MCP23008::getPullup8(uint8_t &mask)
|
||||
{
|
||||
mask = readReg(MCP23008_PUR_A);
|
||||
mask = readReg(MCP23x08_PUR_A);
|
||||
if (_error != MCP23008_OK)
|
||||
{
|
||||
return false;
|
||||
@ -344,6 +339,108 @@ bool MCP23008::getPullup8(uint8_t &mask)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
//
|
||||
// INTERRUPTS (experimental, see MCP23S17 - #40)
|
||||
//
|
||||
// TODO, catch writeReg errors
|
||||
// TODO, MCP23x08_INT_MODE_ERROR?
|
||||
// TODO, if register not changed no need to update?
|
||||
// TODO, 8 bits optimize? more code vs speed?
|
||||
//
|
||||
// pin = 0..7, mode = { RISING, FALLING, CHANGE }
|
||||
bool MCP23008::enableInterrupt(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
if (pin > 7)
|
||||
{
|
||||
_error = MCP23008_PIN_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
// right mode
|
||||
uint8_t intcon = readReg(MCP23x08_INTCON_A);
|
||||
if (mode == CHANGE)
|
||||
{
|
||||
// compare to previous value.
|
||||
intcon &= ~(1 << pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t defval = readReg(MCP23x08_DEFVAL_A);
|
||||
if (mode == RISING)
|
||||
{
|
||||
intcon |= (1 << pin);
|
||||
defval &= ~(1 << pin); // RISING == compare to 0
|
||||
}
|
||||
else if (mode == FALLING)
|
||||
{
|
||||
intcon |= (1 << pin);
|
||||
defval |= ~(1 << pin); // FALLING == compare to 1
|
||||
}
|
||||
writeReg(MCP23x08_DEFVAL_A, defval);
|
||||
}
|
||||
writeReg(MCP23x08_INTCON_A, intcon);
|
||||
|
||||
// enable interrupt
|
||||
uint16_t value = readReg(MCP23x08_GPINTEN_A);
|
||||
value |= (1 << pin);
|
||||
return writeReg(MCP23x08_GPINTEN_A, value);
|
||||
}
|
||||
|
||||
|
||||
bool MCP23008::disableInterrupt(uint8_t pin)
|
||||
{
|
||||
if (pin > 7)
|
||||
{
|
||||
_error = MCP23008_PIN_ERROR;
|
||||
return false;
|
||||
}
|
||||
// disable interrupt
|
||||
uint16_t value = readReg(MCP23x08_GPINTEN_A);
|
||||
value &= ~(1 << pin);
|
||||
return writeReg(MCP23x08_GPINTEN_A, value);
|
||||
}
|
||||
|
||||
|
||||
// which pins caused the INT?
|
||||
uint8_t MCP23008::getInterruptFlagRegister()
|
||||
{
|
||||
return readReg(MCP23x08_INTF_A);
|
||||
}
|
||||
|
||||
|
||||
uint8_t MCP23008::getInterruptCaptureRegister()
|
||||
{
|
||||
return readReg(MCP23x08_INTCAP_A);
|
||||
}
|
||||
|
||||
|
||||
// polarity: 0 = LOW, 1 = HIGH, 2 = NONE/ODR
|
||||
bool MCP23008::setInterruptPolarity(uint8_t polarity)
|
||||
{
|
||||
if (polarity > 2) return false;
|
||||
uint8_t reg = readReg(MCP23x08_IOCR);
|
||||
reg &= ~(MCP23x08_IOCR_ODR | MCP23x08_IOCR_INTPOL);
|
||||
// LOW is default set.
|
||||
if (polarity == 2) reg |= MCP23x08_IOCR_ODR;
|
||||
if (polarity == 1) reg |= MCP23x08_IOCR_INTPOL;
|
||||
return writeReg(MCP23x08_IOCR, reg);
|
||||
}
|
||||
|
||||
|
||||
uint8_t MCP23008::getInterruptPolarity()
|
||||
{
|
||||
uint8_t reg = readReg(MCP23x08_IOCR);
|
||||
if (reg & MCP23x08_IOCR_ODR) return 2;
|
||||
if (reg & MCP23x08_IOCR_INTPOL) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//
|
||||
// MISC
|
||||
//
|
||||
int MCP23008::lastError()
|
||||
{
|
||||
int e = _error;
|
||||
@ -352,6 +449,22 @@ int MCP23008::lastError()
|
||||
}
|
||||
|
||||
|
||||
bool MCP23008::enableControlRegister(uint8_t mask)
|
||||
{
|
||||
uint8_t reg = readReg(MCP23x08_IOCR);
|
||||
reg |= mask;
|
||||
return writeReg(MCP23x08_IOCR, reg);
|
||||
}
|
||||
|
||||
|
||||
bool MCP23008::disableControlRegister(uint8_t mask)
|
||||
{
|
||||
uint8_t reg = readReg(MCP23x08_IOCR);
|
||||
reg &= ~mask;
|
||||
return writeReg(MCP23x08_IOCR, reg);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//
|
||||
// DEBUG
|
||||
@ -364,7 +477,7 @@ uint8_t MCP23008::getPinMode8()
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE
|
||||
// PROTECTED
|
||||
//
|
||||
bool MCP23008::writeReg(uint8_t reg, uint8_t value)
|
||||
{
|
||||
@ -390,16 +503,13 @@ uint8_t MCP23008::readReg(uint8_t reg)
|
||||
_error = MCP23008_I2C_ERROR;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_error = MCP23008_OK;
|
||||
}
|
||||
uint8_t n = _wire->requestFrom(_address, (uint8_t)1);
|
||||
if (n != 1)
|
||||
{
|
||||
_error = MCP23008_I2C_ERROR;
|
||||
return 0;
|
||||
}
|
||||
_error = MCP23008_OK;
|
||||
return _wire->read();
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// FILE: MCP23008.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.2
|
||||
// VERSION: 0.3.3
|
||||
// PURPOSE: Arduino library for I2C MCP23008 8 channel port expander
|
||||
// DATE: 2022-01-10
|
||||
// URL: https://github.com/RobTillaart/MCP23008
|
||||
@ -10,18 +10,18 @@
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
#include "MCP23x08_registers.h"
|
||||
|
||||
|
||||
#define MCP23008_LIB_VERSION (F("0.3.2"))
|
||||
#define MCP23008_LIB_VERSION (F("0.3.3"))
|
||||
|
||||
#define MCP23008_OK 0x00
|
||||
#define MCP23008_PIN_ERROR 0x81
|
||||
#define MCP23008_I2C_ERROR 0x82
|
||||
#define MCP23008_VALUE_ERROR 0x83
|
||||
#define MCP23008_PORT_ERROR 0x84
|
||||
|
||||
|
||||
#define MCP23008_INVALID_READ -100
|
||||
#define MCP23008_REGISTER_ERROR 0xFF
|
||||
#define MCP23008_INVALID_READ 0xFF
|
||||
|
||||
|
||||
class MCP23008
|
||||
@ -29,44 +29,64 @@ class MCP23008
|
||||
public:
|
||||
MCP23008(uint8_t address, TwoWire *wire = &Wire);
|
||||
|
||||
bool begin(bool pullup = true);
|
||||
bool isConnected();
|
||||
uint8_t getAddress();
|
||||
bool begin(bool pullup = true);
|
||||
bool isConnected();
|
||||
uint8_t getAddress();
|
||||
|
||||
|
||||
// single pin interface
|
||||
// mode = INPUT, OUTPUT or INPUT_PULLUP (== INPUT)
|
||||
bool pinMode1(uint8_t pin, uint8_t mode);
|
||||
bool write1(uint8_t pin, uint8_t value);
|
||||
uint8_t read1(uint8_t pin);
|
||||
// single pin interface
|
||||
// mode: 0 = OUTPUT, 1 = INPUT, 1 = INPUT_PULLUP (==INPUT)
|
||||
bool pinMode1(uint8_t pin, uint8_t mode);
|
||||
bool write1(uint8_t pin, uint8_t value);
|
||||
uint8_t read1(uint8_t pin);
|
||||
|
||||
bool setPolarity(uint8_t pin, bool reversed);
|
||||
bool getPolarity(uint8_t pin, bool &reversed);
|
||||
bool setPullup(uint8_t pin, bool pullup);
|
||||
bool getPullup(uint8_t pin, bool &pullup);
|
||||
bool setPolarity(uint8_t pin, bool reversed);
|
||||
bool getPolarity(uint8_t pin, bool &reversed);
|
||||
bool setPullup(uint8_t pin, bool pullup);
|
||||
bool getPullup(uint8_t pin, bool &pullup);
|
||||
|
||||
|
||||
// 8 pins interface
|
||||
// value = bit pattern
|
||||
bool pinMode8(uint8_t value);
|
||||
bool write8(uint8_t value);
|
||||
int read8();
|
||||
// 8 pins interface
|
||||
// value = bit pattern
|
||||
bool pinMode8(uint8_t value);
|
||||
bool write8(uint8_t value);
|
||||
int read8();
|
||||
|
||||
bool setPolarity8(uint8_t mask);
|
||||
bool getPolarity8(uint8_t &mask);
|
||||
bool setPullup8(uint8_t mask);
|
||||
bool getPullup8(uint8_t &mask);
|
||||
bool setPolarity8(uint8_t mask);
|
||||
bool getPolarity8(uint8_t &mask);
|
||||
bool setPullup8(uint8_t mask);
|
||||
bool getPullup8(uint8_t &mask);
|
||||
|
||||
|
||||
int lastError();
|
||||
// INTERRUPTS (experimental)
|
||||
// pin = 0..7, mode = { RISING, FALLING, CHANGE }
|
||||
bool enableInterrupt(uint8_t pin, uint8_t mode);
|
||||
bool disableInterrupt(uint8_t pin);
|
||||
|
||||
// DEBUG functions
|
||||
uint8_t getPinMode8();
|
||||
// which pins caused the INT?
|
||||
uint8_t getInterruptFlagRegister();
|
||||
uint8_t getInterruptCaptureRegister();
|
||||
|
||||
// polarity: 0 = LOW, 1 = HIGH, 2 = NONE/ODR
|
||||
bool setInterruptPolarity(uint8_t polarity);
|
||||
uint8_t getInterruptPolarity();
|
||||
|
||||
// debugging
|
||||
int lastError();
|
||||
|
||||
// set/clear IOCR bit fields
|
||||
bool enableControlRegister(uint8_t mask);
|
||||
bool disableControlRegister(uint8_t mask);
|
||||
|
||||
// DEBUG functions
|
||||
uint8_t getPinMode8();
|
||||
|
||||
|
||||
private:
|
||||
bool writeReg(uint8_t reg, uint8_t value);
|
||||
uint8_t readReg(uint8_t reg);
|
||||
protected:
|
||||
// access to low level registers (just make these functions public).
|
||||
// USE WITH CARE !!!
|
||||
bool writeReg(uint8_t reg, uint8_t value);
|
||||
uint8_t readReg(uint8_t reg);
|
||||
|
||||
uint8_t _address;
|
||||
TwoWire* _wire;
|
||||
|
34
libraries/MCP23008/MCP23x08_registers.h
Normal file
34
libraries/MCP23008/MCP23x08_registers.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: MCP23x08_registers.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: MCP23x08 register file
|
||||
// URL: https://github.com/RobTillaart/MCP23008
|
||||
// URL: https://github.com/RobTillaart/MCP23S08
|
||||
|
||||
|
||||
// Registers // description datasheet P9
|
||||
#define MCP23x08_DDR_A 0x00 // Data Direction Register A P 10
|
||||
#define MCP23x08_POL_A 0x01 // Input Polarity A P 11
|
||||
#define MCP23x08_GPINTEN_A 0x02 // NOT USED interrupt enable P 12
|
||||
#define MCP23x08_DEFVAL_A 0x03 // NOT USED interrupt def P 13
|
||||
#define MCP23x08_INTCON_A 0x04 // NOT USED interrupt control P 14
|
||||
#define MCP23x08_IOCR 0x05 // IO control register P 15
|
||||
#define MCP23x08_PUR_A 0x06 // Pull Up Resistors A P 16
|
||||
#define MCP23x08_INTF_A 0x07 // NOT USED interrupt flag P 17
|
||||
#define MCP23x08_INTCAP_A 0x08 // NOT USED interrupt capture P 18
|
||||
#define MCP23x08_GPIO_A 0x09 // General Purpose IO A P 19
|
||||
#define MCP23x08_OLAT_A 0x0A // NOT USED output latch P 20
|
||||
|
||||
|
||||
// IOCR = IO CONTROL REGISTER bit masks - details datasheet P15
|
||||
#define MCP23x08_IOCR_SEQOP 0x20 // Sequential Operation mode bit.
|
||||
#define MCP23x08_IOCR_DISSLW 0x10 // Slew Rate control bit for SDA output.
|
||||
#define MCP23x08_IOCR_HAEN 0x08 // Hardware Address Enable bit (MCP23S17 only).
|
||||
#define MCP23x08_IOCR_ODR 0x04 // Configures the INT pin as an open-drain output.
|
||||
#define MCP23x08_IOCR_INTPOL 0x02 // This bit sets the polarity of the INT output pin.
|
||||
#define MCP23x08_IOCR_NI 0x01 // Not implemented.
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
@ -73,6 +73,31 @@ before calling **begin()**.
|
||||
- https://github.com/RobTillaart/PCF8574
|
||||
|
||||
|
||||
## I2C
|
||||
|
||||
Supports 100kHz, 400kHz and 1.7MHz
|
||||
|
||||
TODO - add performance data
|
||||
|
||||
|
||||
#### I2C multiplexing
|
||||
|
||||
Sometimes you need to control more devices than possible with the default
|
||||
address range the device provides.
|
||||
This is possible with an I2C multiplexer e.g. TCA9548 which creates up
|
||||
to eight channels (think of it as I2C subnets) which can use the complete
|
||||
address range of the device.
|
||||
|
||||
Drawback of using a multiplexer is that it takes more administration in
|
||||
your code e.g. which device is on which channel.
|
||||
This will slow down the access, which must be taken into account when
|
||||
deciding which devices are on which channel.
|
||||
Also note that switching between channels will slow down other devices
|
||||
too if they are behind the multiplexer.
|
||||
|
||||
- https://github.com/RobTillaart/TCA9548
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
```cpp
|
||||
@ -114,6 +139,58 @@ Returns true if successful.
|
||||
- **bool getPullup8(uint8_t &mask)** reads pull-up for 8 channels at once. Returns true if successful.
|
||||
|
||||
|
||||
### Interrupts (experimental 0.3.3)
|
||||
|
||||
Read the datasheet for the details. Page 21.
|
||||
Note: Error handling is limited.
|
||||
|
||||
pin = 0..7
|
||||
mode = { RISING, FALLING, CHANGE }
|
||||
- **bool enableInterrupt(uint8_t pin, uint8_t mode)**
|
||||
Returns true if successful.
|
||||
Returns MCP23017_PIN_ERROR if pin > 7.
|
||||
- **bool disableInterrupt(uint8_t pin)**
|
||||
Returns true if successful.
|
||||
Returns MCP23017_PIN_ERROR if pin > 7.
|
||||
|
||||
|
||||
Determine which pins caused the Interrupt. (datasheet).
|
||||
- **uint8_t getInterruptFlagRegister()** Reads all 8 pins.
|
||||
- **uint8_t getInterruptCaptureRegister()** Reads all 8 pins.
|
||||
Is used to detect if multiple pins triggered an interrupt.
|
||||
|
||||
|
||||
- **bool setInterruptPolarity(uint8_t ipol)** polarity: 0 = LOW, 1 = HIGH, 2 = NONE/ODR
|
||||
- **uint8_t getInterruptPolarity()** return set value.
|
||||
|
||||
|
||||
### IO Control Register
|
||||
|
||||
The library supports setting bit fields in the IO control register.
|
||||
Read the datasheet carefully!
|
||||
|
||||
- **bool enableControlRegister(uint8_t mask)** set IOCR bit fields
|
||||
- **bool disableControlRegister(uint8_t mask)** clear IOCR bit fields
|
||||
|
||||
|
||||
| constant | mask | description |
|
||||
|:-----------------------|:------:|:--------------|
|
||||
| MCP23x17_IOCR_BANK | 0x80 | Controls how the registers are addressed.
|
||||
| MCP23x17_IOCR_MIRROR | 0x40 | INT Pins Mirror bit.
|
||||
| MCP23x17_IOCR_SEQOP | 0x20 | Sequential Operation mode bit.
|
||||
| MCP23x17_IOCR_DISSLW | 0x10 | Slew Rate control bit for SDA output.
|
||||
| MCP23x17_IOCR_HAEN | 0x08 | Hardware Address Enable bit (MCP23S17 only).
|
||||
| MCP23x17_IOCR_ODR | 0x04 | Configures the INT pin as an open-drain output.
|
||||
| MCP23x17_IOCR_INTPOL | 0x02 | This bit sets the polarity of the INT output pin.
|
||||
| MCP23x17_IOCR_NI | 0x01 | Not implemented.
|
||||
|
||||
|
||||
Two dedicated functions are added: (MCP23S17 only)
|
||||
|
||||
- **bool enableHardwareAddress()** set IOCR_HAEN bit.
|
||||
- **bool disableHardwareAddress()** clear IOCR_HAEN bit.
|
||||
|
||||
|
||||
### Error codes
|
||||
|
||||
If one of the above functions return false, there might be an error.
|
||||
@ -121,18 +198,15 @@ 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 **MCP23008_OK**.
|
||||
|
||||
| DESCRIPTION | VALUE |
|
||||
|:-----------------------|:-------:|
|
||||
| MCP23008_OK | 0x00 |
|
||||
| MCP23008_PIN_ERROR | 0x81 |
|
||||
| MCP23008_I2C_ERROR | 0x82 |
|
||||
| MCP23008_VALUE_ERROR | 0x83 |
|
||||
| MCP23008_PORT_ERROR | 0x84 |
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
See examples.
|
||||
| name | value | description |
|
||||
|:--------------------------|:-------:|:--------------|
|
||||
| MCP23008_OK | 0x00 | No error |
|
||||
| MCP23008_PIN_ERROR | 0x81 |
|
||||
| MCP23008_I2C_ERROR | 0x82 | (compatibility)
|
||||
| MCP23008_VALUE_ERROR | 0x83 |
|
||||
| MCP23008_PORT_ERROR | 0x84 |
|
||||
| MCP23008_REGISTER_ERROR | 0xFF | low level.
|
||||
| MCP23008_INVALID_READ | 0xFF | low level.
|
||||
|
||||
|
||||
## Future
|
||||
|
BIN
libraries/MCP23008/documents/20001952C.pdf
Normal file
BIN
libraries/MCP23008/documents/20001952C.pdf
Normal file
Binary file not shown.
@ -27,10 +27,24 @@ getPolarity8 KEYWORD2
|
||||
setPullup8 KEYWORD2
|
||||
getPullup8 KEYWORD2
|
||||
|
||||
lastError KEYWORD2
|
||||
enableInterrupt KEYWORD2
|
||||
disableInterrupt KEYWORD2
|
||||
|
||||
getInterruptFlagRegister KEYWORD2
|
||||
getInterruptCaptureRegister KEYWORD2
|
||||
setInterruptPolarity KEYWORD2
|
||||
getInterruptPolarity KEYWORD2
|
||||
|
||||
mirrorInterrupts KEYWORD2
|
||||
isMirroredInterrupts KEYWORD2
|
||||
|
||||
getPinMode8 KEYWORD2
|
||||
|
||||
enableControlRegister KEYWORD2
|
||||
disableControlRegister KEYWORD2
|
||||
enableHardwareAddress KEYWORD2
|
||||
disableHardwareAddress KEYWORD2
|
||||
|
||||
|
||||
# Instances (KEYWORD2)
|
||||
|
||||
@ -43,5 +57,6 @@ MCP23008_PIN_ERROR LITERAL1
|
||||
MCP23008_I2C_ERROR LITERAL1
|
||||
MCP23008_VALUE_ERROR LITERAL1
|
||||
MCP23008_PORT_ERROR LITERAL1
|
||||
MCP23008_REGISTER_ERROR LITERAL1
|
||||
MCP23008_INVALID_READ LITERAL1
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/MCP23008.git"
|
||||
},
|
||||
"version": "0.3.2",
|
||||
"version": "0.3.3",
|
||||
"license": "MIT",
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=MCP23008
|
||||
version=0.3.2
|
||||
version=0.3.3
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for I2C MCP23008 8 channel port expander 8 IO-lines
|
||||
|
@ -49,12 +49,12 @@ unittest_teardown()
|
||||
|
||||
unittest(test_constants)
|
||||
{
|
||||
assertEqual(MCP23008_OK , 0x00);
|
||||
assertEqual(MCP23008_PIN_ERROR , 0x81);
|
||||
assertEqual(MCP23008_I2C_ERROR , 0x82);
|
||||
assertEqual(MCP23008_VALUE_ERROR , 0x83);
|
||||
assertEqual(MCP23008_PORT_ERROR , 0x84);
|
||||
assertEqual(MCP23008_INVALID_READ, -100);
|
||||
assertEqual(MCP23008_OK , 0x00);
|
||||
assertEqual(MCP23008_PIN_ERROR , 0x81);
|
||||
assertEqual(MCP23008_I2C_ERROR , 0x82);
|
||||
assertEqual(MCP23008_VALUE_ERROR , 0x83);
|
||||
assertEqual(MCP23008_REGISTER_ERROR, 0xFF);
|
||||
assertEqual(MCP23008_INVALID_READ , 0xFF);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user