mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.2.0 MCP23S08
This commit is contained in:
parent
1e91fd7d38
commit
7e1e45dfb1
@ -11,3 +11,5 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
library-manager: update
|
library-manager: update
|
||||||
compliance: strict
|
compliance: strict
|
||||||
|
verbose: false
|
||||||
|
|
||||||
|
@ -6,12 +6,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
|||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
|
||||||
|
## [0.2.0] - 2023-08-19
|
||||||
|
- add ESP32 support
|
||||||
|
- sync with MCP23S17
|
||||||
|
- add **getAddress()**
|
||||||
|
- add **MCP23S08_registers.h**
|
||||||
|
- update readme.md
|
||||||
|
- update examples
|
||||||
|
- minor edits
|
||||||
|
|
||||||
|
|
||||||
## [0.1.3] - 2023-02-04
|
## [0.1.3] - 2023-02-04
|
||||||
- UPDATE README.MD
|
- UPDATE README.MD
|
||||||
- update GitHub actions
|
- update GitHub actions
|
||||||
- update license 2023
|
- update license 2023
|
||||||
|
|
||||||
|
|
||||||
## [0.1.2] - 2022-11-17
|
## [0.1.2] - 2022-11-17
|
||||||
- add RP2040 in build-CI
|
- add RP2040 in build-CI
|
||||||
- add changelog.md
|
- add changelog.md
|
||||||
|
@ -1,38 +1,19 @@
|
|||||||
//
|
//
|
||||||
// FILE: MCP23S08.cpp
|
// FILE: MCP23S08.cpp
|
||||||
// AUTHOR: Rob Tillaart
|
// AUTHOR: Rob Tillaart
|
||||||
// VERSION: 0.1.3
|
// VERSION: 0.2.0
|
||||||
// PURPOSE: Arduino library for SPI MCP23S08 8 channel port expander
|
// PURPOSE: Arduino library for SPI MCP23S08 8 channel port expander
|
||||||
// DATE: 2022-01-10
|
// DATE: 2022-01-10
|
||||||
// URL: https://github.com/RobTillaart/MCP23S08
|
// URL: https://github.com/RobTillaart/MCP23S08
|
||||||
|
|
||||||
|
|
||||||
#include "Arduino.h"
|
|
||||||
#include "MCP23S08.h"
|
#include "MCP23S08.h"
|
||||||
|
|
||||||
|
|
||||||
// Registers // description datasheet P9
|
// SOFTWARE SPI
|
||||||
#define MCP23S08_DDR_A 0x00 // Data Direction Register A P 10
|
|
||||||
#define MCP23S08_POL_A 0x01 // Input Polarity A P 11
|
|
||||||
#define MCP23S08_GPINTEN_A 0x02 // NOT USED interrupt enable P 12
|
|
||||||
#define MCP23S08_DEFVAL_A 0x03 // NOT USED interrupt def P 13
|
|
||||||
#define MCP23S08_INTCON_A 0x04 // NOT USED interrupt control P 14
|
|
||||||
#define MCP23S08_IOCR 0x05 // IO control register P 15
|
|
||||||
#define MCP23S08_PUR_A 0x06 // Pull Up Resistors A P 16
|
|
||||||
#define MCP23S08_INTF_A 0x07 // NOT USED interrupt flag P 17
|
|
||||||
#define MCP23S08_INTCAP_A 0x08 // NOT USED interrupt capture P 18
|
|
||||||
#define MCP23S08_GPIO_A 0x09 // General Purpose IO A P 19
|
|
||||||
#define MCP23S08_OLAT_A 0x0A // NOT USED output latch P 20
|
|
||||||
|
|
||||||
|
|
||||||
// low level read / write masks
|
|
||||||
#define MCP23S08_WRITE_REG 0x40
|
|
||||||
#define MCP23S08_READ_REG 0x41
|
|
||||||
|
|
||||||
|
|
||||||
MCP23S08::MCP23S08(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address)
|
MCP23S08::MCP23S08(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address)
|
||||||
{
|
{
|
||||||
_address = address;
|
_address = (address << 1);
|
||||||
_select = select;
|
_select = select;
|
||||||
_dataIn = dataIn;
|
_dataIn = dataIn;
|
||||||
_dataOut = dataOut;
|
_dataOut = dataOut;
|
||||||
@ -42,11 +23,20 @@ MCP23S08::MCP23S08(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t cloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MCP23S08::MCP23S08(uint8_t select, uint8_t address)
|
// HARDWARE SPI
|
||||||
|
MCP23S08::MCP23S08(uint8_t select, SPIClass* spi)
|
||||||
{
|
{
|
||||||
_address = address;
|
MCP23S08(select, 0x00, spi);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HARDWARE SPI
|
||||||
|
MCP23S08::MCP23S08(uint8_t select, uint8_t address, SPIClass* spi)
|
||||||
|
{
|
||||||
|
_address = (address << 1);
|
||||||
_select = select;
|
_select = select;
|
||||||
_error = MCP23S08_OK;
|
_error = MCP23S08_OK;
|
||||||
|
_mySPI = spi;
|
||||||
_hwSPI = true;
|
_hwSPI = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,10 +51,24 @@ bool MCP23S08::begin()
|
|||||||
|
|
||||||
if (_hwSPI)
|
if (_hwSPI)
|
||||||
{
|
{
|
||||||
// TODO - ESP32 specific support - see MCP_ADC.
|
#if defined(ESP32)
|
||||||
mySPI = &SPI;
|
if (_useHSPI) // HSPI
|
||||||
mySPI->end();
|
{
|
||||||
mySPI->begin();
|
_mySPI = new SPIClass(HSPI);
|
||||||
|
_mySPI->end();
|
||||||
|
_mySPI->begin(14, 12, 13, _select); // CLK=14 MISO=12 MOSI=13
|
||||||
|
}
|
||||||
|
else // VSPI
|
||||||
|
{
|
||||||
|
_mySPI = new SPIClass(VSPI);
|
||||||
|
_mySPI->end();
|
||||||
|
_mySPI->begin(18, 19, 23, _select); // CLK=18 MISO=19 MOSI=23
|
||||||
|
}
|
||||||
|
#else // generic hardware SPI
|
||||||
|
_mySPI = &SPI;
|
||||||
|
_mySPI->end();
|
||||||
|
_mySPI->begin();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -78,10 +82,14 @@ bool MCP23S08::begin()
|
|||||||
// check connected
|
// check connected
|
||||||
if (! isConnected()) return false;
|
if (! isConnected()) return false;
|
||||||
|
|
||||||
// disable address increment (datasheet)
|
// disable address increment (datasheet P20
|
||||||
if (! writeReg(MCP23S08_IOCR, 0b00100000)) return false; // TODO MAGIC NR
|
// SEQOP: Sequential Operation mode bit
|
||||||
|
// 1 = Sequential operation disabled, address pointer does not increment.
|
||||||
|
// 0 = Sequential operation enabled, address pointer increments.
|
||||||
|
if (! writeReg(MCP23S08_IOCR, MCP23S08_IOCR_SEQOP)) return false;
|
||||||
|
|
||||||
// Force INPUT_PULLUP
|
// Force INPUT_PULLUP
|
||||||
if (! writeReg(MCP23S08_PUR_A, 0xFF)) return false;
|
if (! writeReg(MCP23S08_PUR_A, 0xFF)) return false; // 0xFF == all UP
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +101,16 @@ bool MCP23S08::isConnected()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t MCP23S08::getAddress()
|
||||||
|
{
|
||||||
|
return (_address >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
// single pin interface
|
// single pin interface
|
||||||
|
//
|
||||||
// pin = 0..7
|
// pin = 0..7
|
||||||
// mode = INPUT, OUTPUT, INPUT_PULLUP (= same as INPUT)
|
// mode = INPUT, OUTPUT, INPUT_PULLUP (= same as INPUT)
|
||||||
bool MCP23S08::pinMode(uint8_t pin, uint8_t mode)
|
bool MCP23S08::pinMode(uint8_t pin, uint8_t mode)
|
||||||
@ -151,6 +168,7 @@ bool MCP23S08::digitalWrite(uint8_t pin, uint8_t value)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t mask = 1 << pin;
|
uint8_t mask = 1 << pin;
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
@ -160,6 +178,7 @@ bool MCP23S08::digitalWrite(uint8_t pin, uint8_t value)
|
|||||||
{
|
{
|
||||||
val &= ~mask;
|
val &= ~mask;
|
||||||
}
|
}
|
||||||
|
// only write when changed.
|
||||||
if (pre != val)
|
if (pre != val)
|
||||||
{
|
{
|
||||||
writeReg(IOR, val);
|
writeReg(IOR, val);
|
||||||
@ -302,10 +321,10 @@ void MCP23S08::setSPIspeed(uint32_t speed)
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
//
|
||||||
// 8 pins interface
|
// 8 pins interface
|
||||||
|
//
|
||||||
// whole register at once
|
// whole register at once
|
||||||
// value = 0..0xFF bit pattern
|
// value = 0..0xFF bit pattern
|
||||||
bool MCP23S08::pinMode8(uint8_t value)
|
bool MCP23S08::pinMode8(uint8_t value)
|
||||||
@ -385,11 +404,89 @@ int MCP23S08::lastError()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MCP23S08::enableControlRegister(uint8_t mask)
|
||||||
|
{
|
||||||
|
uint8_t reg = readReg(MCP23S08_IOCR);
|
||||||
|
reg |= mask;
|
||||||
|
writeReg(MCP23S08_IOCR, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MCP23S08::disableControlRegister(uint8_t mask)
|
||||||
|
{
|
||||||
|
uint8_t reg = readReg(MCP23S08_IOCR);
|
||||||
|
reg &= ~mask;
|
||||||
|
writeReg(MCP23S08_IOCR, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MCP23S08::enableHardwareAddress()
|
||||||
|
{
|
||||||
|
enableControlRegister(MCP23S08_IOCR_HAEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MCP23S08::disableHardwareAddress()
|
||||||
|
{
|
||||||
|
disableControlRegister(MCP23S08_IOCR_HAEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(ESP32)
|
||||||
|
|
||||||
|
void MCP23S08::selectHSPI()
|
||||||
|
{
|
||||||
|
_useHSPI = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MCP23S08::selectVSPI()
|
||||||
|
{
|
||||||
|
_useHSPI = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MCP23S08::usesHSPI()
|
||||||
|
{
|
||||||
|
return _useHSPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MCP23S08::usesVSPI()
|
||||||
|
{
|
||||||
|
return !_useHSPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MCP23S08::setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)
|
||||||
|
{
|
||||||
|
_clock = clk;
|
||||||
|
_dataOut = mosi;
|
||||||
|
_dataIn = miso;
|
||||||
|
_select = select;
|
||||||
|
pinMode(_select, OUTPUT);
|
||||||
|
digitalWrite(_select, HIGH);
|
||||||
|
|
||||||
|
_mySPI->end(); // disable old SPI
|
||||||
|
|
||||||
|
_mySPI->begin(clk, miso, mosi, select); // enable new pins
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// PRIVATE
|
// PRIVATE
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
// low level read / write masks
|
||||||
|
#define MCP23S08_WRITE_REG 0x40
|
||||||
|
#define MCP23S08_READ_REG 0x41
|
||||||
|
|
||||||
|
|
||||||
bool MCP23S08::writeReg(uint8_t reg, uint8_t value)
|
bool MCP23S08::writeReg(uint8_t reg, uint8_t value)
|
||||||
{
|
{
|
||||||
_error = MCP23S08_OK;
|
_error = MCP23S08_OK;
|
||||||
@ -402,15 +499,17 @@ bool MCP23S08::writeReg(uint8_t reg, uint8_t value)
|
|||||||
::digitalWrite(_select, LOW);
|
::digitalWrite(_select, LOW);
|
||||||
if (_hwSPI)
|
if (_hwSPI)
|
||||||
{
|
{
|
||||||
mySPI->beginTransaction(_spi_settings);
|
_mySPI->beginTransaction(_spi_settings);
|
||||||
mySPI->transfer(MCP23S08_WRITE_REG | (_address << 1) );
|
// _address already shifted
|
||||||
mySPI->transfer(reg);
|
_mySPI->transfer(MCP23S08_WRITE_REG | _address );
|
||||||
mySPI->transfer(value);
|
_mySPI->transfer(reg);
|
||||||
mySPI->endTransaction();
|
_mySPI->transfer(value);
|
||||||
|
_mySPI->endTransaction();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
swSPI_transfer(MCP23S08_WRITE_REG | (_address << 1) );
|
// _address already shifted
|
||||||
|
swSPI_transfer(MCP23S08_WRITE_REG | _address );
|
||||||
swSPI_transfer(reg);
|
swSPI_transfer(reg);
|
||||||
swSPI_transfer(value);
|
swSPI_transfer(value);
|
||||||
}
|
}
|
||||||
@ -434,15 +533,17 @@ uint8_t MCP23S08::readReg(uint8_t reg)
|
|||||||
::digitalWrite(_select, LOW);
|
::digitalWrite(_select, LOW);
|
||||||
if (_hwSPI)
|
if (_hwSPI)
|
||||||
{
|
{
|
||||||
mySPI->beginTransaction(_spi_settings);
|
_mySPI->beginTransaction(_spi_settings);
|
||||||
mySPI->transfer(MCP23S08_READ_REG | (_address << 1) ); // TODO OPTIMIZE n times
|
// _address already shifted
|
||||||
mySPI->transfer(reg);
|
_mySPI->transfer(MCP23S08_READ_REG | _address ); // TODO OPTIMIZE n times
|
||||||
rv = mySPI->transfer(0xFF);
|
_mySPI->transfer(reg);
|
||||||
mySPI->endTransaction();
|
rv = _mySPI->transfer(0xFF);
|
||||||
|
_mySPI->endTransaction();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
swSPI_transfer(MCP23S08_READ_REG | (_address << 1) );
|
// _address already shifted
|
||||||
|
swSPI_transfer(MCP23S08_READ_REG | _address );
|
||||||
swSPI_transfer(reg);
|
swSPI_transfer(reg);
|
||||||
rv = swSPI_transfer(0xFF);
|
rv = swSPI_transfer(0xFF);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
//
|
//
|
||||||
// FILE: MCP23S08.h
|
// FILE: MCP23S08.h
|
||||||
// AUTHOR: Rob Tillaart
|
// AUTHOR: Rob Tillaart
|
||||||
// VERSION: 0.1.3
|
// VERSION: 0.2.0
|
||||||
// PURPOSE: Arduino library for SPI MCP23S08 8 channel port expander
|
// PURPOSE: Arduino library for SPI MCP23S08 8 channel port expander
|
||||||
// DATE: 2022-01-10
|
// DATE: 2022-01-10
|
||||||
// URL: https://github.com/RobTillaart/MCP23S08
|
// URL: https://github.com/RobTillaart/MCP23S08
|
||||||
@ -10,10 +10,12 @@
|
|||||||
|
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "SPI.h"
|
#include "SPI.h"
|
||||||
|
#include "MCP23S08_registers.h"
|
||||||
|
|
||||||
|
|
||||||
#define MCP23S08_LIB_VERSION (F("0.1.3"))
|
#define MCP23S08_LIB_VERSION (F("0.2.0"))
|
||||||
|
|
||||||
|
// ERROR CODES
|
||||||
#define MCP23S08_OK 0x00
|
#define MCP23S08_OK 0x00
|
||||||
#define MCP23S08_PIN_ERROR 0x81
|
#define MCP23S08_PIN_ERROR 0x81
|
||||||
#define MCP23S08_SPI_ERROR 0x82
|
#define MCP23S08_SPI_ERROR 0x82
|
||||||
@ -24,20 +26,26 @@
|
|||||||
#define MCP23S08_INVALID_READ -100
|
#define MCP23S08_INVALID_READ -100
|
||||||
|
|
||||||
|
|
||||||
|
const uint32_t MCP23S08_TYP_SPI_SPEED = 8000000;
|
||||||
|
const uint32_t MCP23S08_MAX_SPI_SPEED = 10000000;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MCP23S08
|
class MCP23S08
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// SOFTWARE SPI
|
// SOFTWARE SPI
|
||||||
MCP23S08(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address = 0x00);
|
MCP23S08(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address = 0x00);
|
||||||
// HARDWARE SPI
|
// HARDWARE SPI
|
||||||
MCP23S08(uint8_t select, uint8_t address = 0x00);
|
MCP23S08(uint8_t select, SPIClass* spi);
|
||||||
|
MCP23S08(uint8_t select, uint8_t address = 0x00, SPIClass* spi = &SPI);
|
||||||
|
|
||||||
bool begin();
|
bool begin();
|
||||||
bool isConnected(); // needed ?
|
bool isConnected();
|
||||||
|
uint8_t getAddress();
|
||||||
|
|
||||||
// single pin interface
|
// single pin interface
|
||||||
// mode = INPUT, OUTPUT or INPUT_PULLUP (==INPUT)
|
// mode: 0 = OUTPUT, 1 = INPUT, 1 = INPUT_PULLUP (==INPUT)
|
||||||
bool pinMode(uint8_t pin, uint8_t mode);
|
bool pinMode(uint8_t pin, uint8_t mode);
|
||||||
bool digitalWrite(uint8_t pin, uint8_t value);
|
bool digitalWrite(uint8_t pin, uint8_t value);
|
||||||
uint8_t digitalRead(uint8_t pin);
|
uint8_t digitalRead(uint8_t pin);
|
||||||
@ -49,7 +57,6 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
// 8 pins interface
|
// 8 pins interface
|
||||||
// port = 0..1
|
|
||||||
// value = bit pattern
|
// value = bit pattern
|
||||||
bool pinMode8(uint8_t value);
|
bool pinMode8(uint8_t value);
|
||||||
bool write8(uint8_t value);
|
bool write8(uint8_t value);
|
||||||
@ -69,7 +76,30 @@ public:
|
|||||||
bool usesHWSPI() { return _hwSPI; };
|
bool usesHWSPI() { return _hwSPI; };
|
||||||
int lastError();
|
int lastError();
|
||||||
|
|
||||||
|
// set/clear IOCR bit fields (0.2.0 experimental)
|
||||||
|
void enableControlRegister(uint8_t mask);
|
||||||
|
void disableControlRegister(uint8_t mask);
|
||||||
|
// 0.2.0 experimental
|
||||||
|
void enableHardwareAddress();
|
||||||
|
void disableHardwareAddress();
|
||||||
|
|
||||||
|
// ESP32 specific
|
||||||
|
#if defined(ESP32)
|
||||||
|
|
||||||
|
void selectHSPI();
|
||||||
|
void selectVSPI();
|
||||||
|
bool usesHSPI();
|
||||||
|
bool usesVSPI();
|
||||||
|
|
||||||
|
// to overrule the ESP32s default hardware pins
|
||||||
|
void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// access to low level registers (just make these two functions public).
|
||||||
|
// USE WITH CARE !!!
|
||||||
bool writeReg(uint8_t reg, uint8_t value);
|
bool writeReg(uint8_t reg, uint8_t value);
|
||||||
uint8_t readReg(uint8_t reg);
|
uint8_t readReg(uint8_t reg);
|
||||||
|
|
||||||
@ -80,15 +110,20 @@ private:
|
|||||||
uint8_t _clock = 0;
|
uint8_t _clock = 0;
|
||||||
uint8_t _error = MCP23S08_OK;
|
uint8_t _error = MCP23S08_OK;
|
||||||
|
|
||||||
bool _hwSPI = false;
|
bool _hwSPI = false;
|
||||||
// 1 MHz is a safe value TODO CHECK datasheet
|
|
||||||
uint32_t _SPIspeed = 8000000UL;
|
// 10 MHz is maximum, 8 is a better clock divider on AVR.
|
||||||
SPIClass * mySPI;
|
uint32_t _SPIspeed = MCP23S08_TYP_SPI_SPEED;
|
||||||
|
SPIClass * _mySPI;
|
||||||
SPISettings _spi_settings;
|
SPISettings _spi_settings;
|
||||||
|
|
||||||
uint8_t swSPI_transfer(uint8_t val);
|
uint8_t swSPI_transfer(uint8_t val);
|
||||||
|
|
||||||
|
#if defined(ESP32)
|
||||||
|
bool _useHSPI = true;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// -- END OF FILE --
|
// -- END OF FILE --
|
||||||
|
|
||||||
|
33
libraries/MCP23S08/MCP23S08_registers.h
Normal file
33
libraries/MCP23S08/MCP23S08_registers.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
//
|
||||||
|
// FILE: MCP23S08_registers.h
|
||||||
|
// AUTHOR: Rob Tillaart
|
||||||
|
// PURPOSE: MCP23S08 register file
|
||||||
|
// URL: https://github.com/RobTillaart/MCP23S08
|
||||||
|
|
||||||
|
|
||||||
|
// Registers // description datasheet P9
|
||||||
|
#define MCP23S08_DDR_A 0x00 // Data Direction Register A P 10
|
||||||
|
#define MCP23S08_POL_A 0x01 // Input Polarity A P 11
|
||||||
|
#define MCP23S08_GPINTEN_A 0x02 // NOT USED interrupt enable P 12
|
||||||
|
#define MCP23S08_DEFVAL_A 0x03 // NOT USED interrupt def P 13
|
||||||
|
#define MCP23S08_INTCON_A 0x04 // NOT USED interrupt control P 14
|
||||||
|
#define MCP23S08_IOCR 0x05 // IO control register P 15
|
||||||
|
#define MCP23S08_PUR_A 0x06 // Pull Up Resistors A P 16
|
||||||
|
#define MCP23S08_INTF_A 0x07 // NOT USED interrupt flag P 17
|
||||||
|
#define MCP23S08_INTCAP_A 0x08 // NOT USED interrupt capture P 18
|
||||||
|
#define MCP23S08_GPIO_A 0x09 // General Purpose IO A P 19
|
||||||
|
#define MCP23S08_OLAT_A 0x0A // NOT USED output latch P 20
|
||||||
|
|
||||||
|
|
||||||
|
// IOCR = IO CONTROL REGISTER bit masks - details datasheet P15
|
||||||
|
#define MCP23S08_IOCR_SEQOP 0x20 // Sequential Operation mode bit.
|
||||||
|
#define MCP23S08_IOCR_DISSLW 0x10 // Slew Rate control bit for SDA output.
|
||||||
|
#define MCP23S08_IOCR_HAEN 0x08 // Hardware Address Enable bit (MCP23S17 only).
|
||||||
|
#define MCP23S08_IOCR_ODR 0x04 // Configures the INT pin as an open-drain output.
|
||||||
|
#define MCP23S08_IOCR_INTPOL 0x02 // This bit sets the polarity of the INT output pin.
|
||||||
|
#define MCP23S08_IOCR_NI 0x01 // Not implemented.
|
||||||
|
|
||||||
|
|
||||||
|
// -- END OF FILE --
|
||||||
|
|
@ -46,15 +46,53 @@ If a pin is not changed it will not be written again to save time.
|
|||||||
|
|
||||||
### Constructor
|
### Constructor
|
||||||
|
|
||||||
- **MCP23S08(uint8_t select, uint8_t data, uint8_t clock)** constructor SW SPI.
|
- **MCP23S08(uint8_t select, uint8_t dataIn, uint8_t dataOut, uint8_t clock, uint8_t address = 0x00)** constructor SOFTWARE SPI.
|
||||||
- **MCP23S08(uint8_t select)** constructor HW SPI.
|
- **MCP23S08(uint8_t select, SPIClass\* spi)** constructor HARDWARE SPI with explicit SPI interface selected.
|
||||||
|
- **MCP23S08(uint8_t select, uint8_t address = 0x00, SPIClass\* spi = &SPI)** constructor HARDWARE SPI with optional address pins and SPI interface.
|
||||||
- **bool begin()** returns true if successful.
|
- **bool begin()** returns true if successful.
|
||||||
- **bool isConnected()** returns true if connected, false otherwise. (dummy)
|
- **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..3.
|
||||||
|
|
||||||
|
The two hardware constructors allow to call 4 different constructors.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
- MCP23S08(10); // select pin only
|
||||||
|
- MCP23S08(10, 7); // select pin + address pins
|
||||||
|
- MCP23S08(10, 7, &SPI2); // select pin + address pins + SPI port
|
||||||
|
- MCP23S08(10, &SPI2); // select pin + SPI port
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Sharing SELECT lines
|
||||||
|
|
||||||
|
(verified in MCP23S17 issue 19)
|
||||||
|
Technically two chips could use the same SELECT pin and a different address.
|
||||||
|
Since 0.2.0 the constructors allow to setup such a configuration.
|
||||||
|
The added value is that one can use up to 4 devices (= 32 IO lines) with only
|
||||||
|
four lines (MISO, MOSI, CLOCK, SELECT).
|
||||||
|
|
||||||
|
I assume that this configuration is less used and IMHO not recommended.
|
||||||
|
NB it is more difficult to detect which device is selected when debugging.
|
||||||
|
|
||||||
|
To use the hardware addresses the Hardware Address ENable register must be set.
|
||||||
|
See datasheet 1.6.6 ADDRESSING SPI DEVICES, need to set IOCON.HAEN.
|
||||||
|
|
||||||
|
The library supports two ways:
|
||||||
|
```cpp
|
||||||
|
MCP.enableControlRegister(MCP23S08_IOCR_HAEN); // or 0x08
|
||||||
|
or
|
||||||
|
MCP.enableHardwareAddress(); // 0.2.0 version and up
|
||||||
|
```
|
||||||
|
|
||||||
|
See also **IO Control Register** section below.
|
||||||
|
|
||||||
|
|
||||||
### Single pin interface
|
### Single pin interface
|
||||||
|
|
||||||
- **bool pinMode(uint8_t pin, uint8_t mode)** pin = 0..7, mode = INPUT, OUTPUT.
|
mode: 0 = OUTPUT, 1 = INPUT, 1 = INPUT_PULLUP (==INPUT)
|
||||||
|
|
||||||
|
- **bool pinMode(uint8_t pin, uint8_t mode)** pin = 0..7.
|
||||||
Returns true if successful.
|
Returns true if successful.
|
||||||
- **bool digitalWrite(uint8_t pin, uint8_t value)** pin = 0..7, value = LOW(0) HIGH (!0).
|
- **bool digitalWrite(uint8_t pin, uint8_t value)** pin = 0..7, value = LOW(0) HIGH (!0).
|
||||||
Returns true if successful.
|
Returns true if successful.
|
||||||
@ -84,6 +122,39 @@ Returns true if successful.
|
|||||||
Returns true if successful.
|
Returns true if successful.
|
||||||
|
|
||||||
|
|
||||||
|
### Other
|
||||||
|
|
||||||
|
- **void setSPIspeed(uint32_t speed)** set hardware speed (8Mb default).
|
||||||
|
- **uint32_t getSPIspeed()** returns set speed.
|
||||||
|
|
||||||
|
|
||||||
|
### Debugging
|
||||||
|
|
||||||
|
- **bool usesHWSPI()** returns true = hardware SPI, false = software SPI.
|
||||||
|
- **int lastError()** idem.
|
||||||
|
|
||||||
|
|
||||||
|
### ControlRegister
|
||||||
|
|
||||||
|
Since 0.2.0
|
||||||
|
|
||||||
|
- **void enableControlRegister(uint8_t mask)** set IOCR bit fields
|
||||||
|
- **void disableControlRegister(uint8_t mask)** clear IOCR bit fields
|
||||||
|
- **void enableHardwareAddress()** specific for HAEN field.
|
||||||
|
- **void disableHardwareAddress()** specific for HAEN field.
|
||||||
|
|
||||||
|
|
||||||
|
### ESP32
|
||||||
|
|
||||||
|
Since 0.2.0
|
||||||
|
|
||||||
|
- **void selectHSPI()** idem
|
||||||
|
- **void selectVSPI()** idem
|
||||||
|
- **bool usesHSPI()** idem
|
||||||
|
- **bool usesVSPI()** idem
|
||||||
|
- **void setGPIOpins(uint8_t clk, uint8_t miso, uint8_t mosi, uint8_t select)** overrule the ESP32s default hardware pins.
|
||||||
|
|
||||||
|
|
||||||
### Error codes
|
### Error codes
|
||||||
|
|
||||||
If one of the above functions return false, there might be an error.
|
If one of the above functions return false, there might be an error.
|
||||||
@ -118,10 +189,7 @@ See examples.
|
|||||||
|
|
||||||
#### Could
|
#### Could
|
||||||
|
|
||||||
- MCP23S17 sync
|
- ESP32 example code
|
||||||
- add enableIO controlRegister functions
|
|
||||||
- add registers.h file
|
|
||||||
|
|
||||||
|
|
||||||
#### Wont
|
#### Wont
|
||||||
|
|
||||||
|
@ -17,8 +17,9 @@ void setup()
|
|||||||
{
|
{
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
Serial.print("MCP23S08_test version: ");
|
Serial.print("MCP23S08_LIB_VERSION: ");
|
||||||
Serial.println(MCP23S08_LIB_VERSION);
|
Serial.println(MCP23S08_LIB_VERSION);
|
||||||
|
Serial.println();
|
||||||
delay(100);
|
delay(100);
|
||||||
|
|
||||||
SPI.begin();
|
SPI.begin();
|
||||||
|
@ -15,8 +15,9 @@ void setup()
|
|||||||
{
|
{
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
Serial.print("MCP23S08_test version: ");
|
Serial.print("MCP23S08_LIB_VERSION: ");
|
||||||
Serial.println(MCP23S08_LIB_VERSION);
|
Serial.println(MCP23S08_LIB_VERSION);
|
||||||
|
Serial.println();
|
||||||
delay(100);
|
delay(100);
|
||||||
|
|
||||||
SPI.begin();
|
SPI.begin();
|
||||||
|
@ -18,7 +18,7 @@ void setup()
|
|||||||
{
|
{
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
Serial.print("MCP23S08_test version: ");
|
Serial.print("MCP23S08_LIB_VERSION: ");
|
||||||
Serial.println(MCP23S08_LIB_VERSION);
|
Serial.println(MCP23S08_LIB_VERSION);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
delay(100);
|
delay(100);
|
||||||
|
62
libraries/MCP23S08/keywords.txt
Normal file
62
libraries/MCP23S08/keywords.txt
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# Syntax Colouring Map For MCP23S08
|
||||||
|
|
||||||
|
# Data types (KEYWORD1)
|
||||||
|
MCP23S08 KEYWORD1
|
||||||
|
|
||||||
|
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
begin KEYWORD2
|
||||||
|
isConnected KEYWORD2
|
||||||
|
getAddress KEYWORD2
|
||||||
|
|
||||||
|
pinMode KEYWORD2
|
||||||
|
digitalWrite KEYWORD2
|
||||||
|
digitalRead KEYWORD2
|
||||||
|
|
||||||
|
setPolarity KEYWORD2
|
||||||
|
getPolarity KEYWORD2
|
||||||
|
setPullup KEYWORD2
|
||||||
|
getPullup KEYWORD2
|
||||||
|
|
||||||
|
pinMode8 KEYWORD2
|
||||||
|
write8 KEYWORD2
|
||||||
|
read8 KEYWORD2
|
||||||
|
|
||||||
|
setPolarity8 KEYWORD2
|
||||||
|
getPolarity8 KEYWORD2
|
||||||
|
setPullup8 KEYWORD2
|
||||||
|
getPullup8 KEYWORD2
|
||||||
|
|
||||||
|
setSPIspeed KEYWORD2
|
||||||
|
getSPIspeed KEYWORD2
|
||||||
|
|
||||||
|
usesHWSPI KEYWORD2
|
||||||
|
lastError KEYWORD2
|
||||||
|
|
||||||
|
enableControlRegister KEYWORD2
|
||||||
|
disableControlRegister KEYWORD2
|
||||||
|
|
||||||
|
enableHardwareAddress KEYWORD2
|
||||||
|
disableHardwareAddress KEYWORD2
|
||||||
|
|
||||||
|
selectHSPI KEYWORD2
|
||||||
|
selectVSPI KEYWORD2
|
||||||
|
usesHSPI KEYWORD2
|
||||||
|
usesVSPI KEYWORD2
|
||||||
|
setGPIOpins KEYWORD2
|
||||||
|
|
||||||
|
|
||||||
|
# Instances (KEYWORD2)
|
||||||
|
|
||||||
|
|
||||||
|
# Constants (LITERAL1)
|
||||||
|
MCP23S08_LIB_VERSION LITERAL1
|
||||||
|
|
||||||
|
MCP23S08_OK LITERAL1
|
||||||
|
MCP23S08_PIN_ERROR LITERAL1
|
||||||
|
MCP23S08_I2C_ERROR LITERAL1
|
||||||
|
MCP23S08_VALUE_ERROR LITERAL1
|
||||||
|
MCP23S08_PORT_ERROR LITERAL1
|
||||||
|
MCP23S08_REGISTER_ERROR LITERAL1
|
||||||
|
MCP23S08_INVALID_READ LITERAL1
|
||||||
|
|
@ -15,7 +15,7 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/RobTillaart/MCP23S08.git"
|
"url": "https://github.com/RobTillaart/MCP23S08.git"
|
||||||
},
|
},
|
||||||
"version": "0.1.3",
|
"version": "0.2.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"frameworks": "arduino",
|
"frameworks": "arduino",
|
||||||
"platforms": "*",
|
"platforms": "*",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name=MCP23S08
|
name=MCP23S08
|
||||||
version=0.1.3
|
version=0.2.0
|
||||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||||
sentence=Arduino library for SPI MCP23S08 8 channel port expander 8 IO-lines
|
sentence=Arduino library for SPI MCP23S08 8 channel port expander 8 IO-lines
|
||||||
|
Loading…
x
Reference in New Issue
Block a user