RobTillaart / MCP23S17

Arduino library for SPI based MCP23S17 16 channel port expander
MIT License
27 stars 11 forks source link

Sharing a single select pin #15

Closed thijstriemstra closed 2 years ago

thijstriemstra commented 2 years ago

The readme mentions:

(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.

Why is this not recommended?

RobTillaart commented 2 years ago

@thijstriemstra

This chip is the only SPI based one I know that has both an address and a SELECT line.

As within SPI one normally uses a SELECT line to select a device, this allows to have multiple device behind one. When I would encounter such in a schema, it would immediately raise questions like:

Only by studying the datasheet / code I will get an answer to those questions. So in short it is outside my expectations.

That said, I think it is ok to use one select pin for multiple devices but never tested it. If you do test it, please let me know your experiences.

(my assumption is that the address is inherited from the I2C version of the chip)

thijstriemstra commented 2 years ago

If you do test it, please let me know your experiences.

I couldn't get it to work.

RobTillaart commented 2 years ago

looked into the datasheet

3.3.2 ADDRESSING SPI DEVICES

The MCP23S17 is a slave SPI device. The slave
address contains four fixed bits and three user-defined
hardware address bits (if enabled via IOCON.HAEN)
(pins A2, A1 and A0) with the read/write bit filling out
the control byte. Figure 3-5 shows the control byte
format. The address pins should be externally biased
even if disabled (IOCON.HAEN = 0).

TABLE 3-4: CONTROL REGISTER SUMMARY (IOCON.BANK = 1)


The library has no call for this, so you need to add something like code below to the library (proto in .h and implementation in .cpp)

void enableHWAddress()
{
  uint8_t reg = readReg(MCP23S17_IOCR);
  reg |= MCP23S17_IOCR_HAEN;
  writeReg(MCP23S17_IOCR, reg);
}

void disableHWAddress()
{
  uint8_t reg = readReg(MCP23S17_IOCR);
  reg &= ~MCP23S17_IOCR_HAEN;
  writeReg(MCP23S17_IOCR, reg);
}
RobTillaart commented 2 years ago

Note to myself: better to make two generic control register calls

void enableControlRegister(uint8_t mask)
{
  uint8_t reg = readReg(MCP23S17_IOCR);
  reg |= mask;
  writeReg(MCP23S17_IOCR, reg);
}

void disableControlRegister(uint8_t mask)
{
  uint8_t reg = readReg(MCP23S17_IOCR);
  reg &= ~mask;
  writeReg(MCP23S17_IOCR, reg);
}

The defines should move from .cpp to .h

RobTillaart commented 2 years ago

@thijstriemstra Created a branch - https://github.com/RobTillaart/MCP23S17/tree/develop that supports the dis- / enableControlRegister(uint8_t mask) functions.

If you have time, can you please check verify if it enables the address stuff (I have no hardware around to test)

masks are in the MCP23S17_registers.h file.

thijstriemstra commented 2 years ago

hi @RobTillaart thanks for taking the time to thoroughly investigate this. Due to time constraints I switched out the 2nd mcp23s17 with an I2C version (mcp23017) for now. I'm sure I'll run into this again in the future and will get back to you, cheers.

RobTillaart commented 2 years ago

OK, I will merge the branch and close the issue.

thijstriemstra commented 2 years ago

thanks. I guess this info is now outdated (and tested instead)?

(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.

RobTillaart commented 2 years ago

No not tested, no HW nearby. And if it works I still doubt I would recommend it for the reasons mentioned earlier.

That said, if you need a lot of IO lines you can do 16 x 8 = 128 IO lines per select pin. And if you use one MCP to control 16 select lines you could control 2048 IO lines in theory. (in theory there is no difference between practice and theory, but in practice there is)