Teensy 4.1 and MCP23S17 question

Sandro

Well-known member
Hi all, in my application I would connect n.6 MCP23S17 to my T4.1, with SPI1 bus, using these pins:
CS1: 38
MISO1: 39
MOSI1: 26
SCK1: 27

The purpose is reading Encoders and pushbutton; here is a sample of my schematics:
sample.png


My requirement are: 1) using the SPI1 bus; 2) read all 16 GPxy pins of a single chip with a single read. (i.e., a full 16-bit read).

I found two libraries, but none of them offers both functionalities:
  • with gpio_MCP23S17 library I can read all GPxy pins of a shifter chip with a single read, but I cannot configure the SPI bus;
  • with Adafruit_MCP23X17 library I can configure the SPI bus, but I cannot read all GPxy pins of a shifter with a single read.

Can anyone suggest another library, or how to make a custom version with one of the previous libraries?

Thank in advance
 
I found two libraries, but none of them offers both functionalities:
  • with gpio_MCP23S17 library I can read all GPxy pins of a shifter chip with a single read, but I cannot configure the SPI bus;
  • with Adafruit_MCP23X17 library I can configure the SPI bus, but I cannot read all GPxy pins of a shifter with a single read.
Can anyone suggest another library, or how to make a custom version with one of the previous libraries?

I googled "github MCP23S17 Arduino" and found this library, which seems to have what you want. I have used some of Rob's libraries and they work well.

 
To access each MCP23S17 individually, you must have 6 separate CS signals. And acivate only one during SPI transfer
 
To access each MCP23S17 individually, you must have 6 separate CS signals. And acivate only one during SPI transfer
Looks from the data sheet as if this is an unusual SPI part which is addressable. Note the A0/1/2 wiring on the posted schematic.
 
Solved.. I din't notice, Adafruit_MCP23X17 has a specific function, which reads all 16 pins:
uint16_t readGPIOAB();

I googled "github MCP23S17 Arduino" and found this library, which seems to have what you want. I have used some of Rob's libraries and they work well.

https://github.com/RobTillaart/MCP23S17
I know this library, and I'd like to use it, because it seems very simple and essential but I've not been able to configure SPI1 as "hardware SPI"
 
Last edited:
Seems easy enough - this looks like the constructor to use:

C++:
MCP23S17(int select, int address = 0x00, __SPI_CLASS__ * spi = &SPI);
Use &SPI1 for the last parameter.

In my case, the SPI1 bus is also used by the display, and managed somewhere inside Adafruit_ILI9341.h library
 
It ought to be possible to have multiple devices on one SPI bus, provided you don't try to access more than one at a time (e.g. by having async display updates running and then reading your encoders); that is kind of the point of SPI having a /CS line for each peripheral. The various Teensy accelerated display drivers do have some issues there, because they assume they know how they left the SPI bus configured, and get confused when it's been changed. If the Arduino display driver, or indeed any SPI-based driver, does the same, then there will be problems.

Best things, as always, is to try a simple example and see if it works! Of course, try each separately before you glue them together...
 
So I have done this before with a display, multiple MCP23S17s, and eight psram chips all on the same SPI bus (it was on an ATMEGA1284p but the idea still works). What you're describing is why there are beginTransaction and endTransaction functions you wrap your SPI transactions with. That way, you can reconfigure the SPI bus for the MCP23S17s and then restore previous settings when done.

Here is an example from an older version of my i960 chipset:

 
A couple years ago we has a conversation on this forum where someone connected several color displays to the SPI port. I believe they were probably ILI9341s, but not 100% sure since it's been quite a while. At first it was pretty unreliable. Ultimately it did work, but only after adding parts to improve the signal quality.

You may or may not encounter those signal quality issues. It really depends on the length and type of wires. Shorter wires with good ground connection close to each wire is best. The longer your wires and the farther the GND current return path is from each wire, the worse signal quality becomes.

If you are designing a PCB, usually 4 layers with an unbroken GND plane on the inner layer just below the signals gives the very best results. On a 2 layer PCB, an unbroken GND plane on the other layer is usually not feasible. Beware of partial GND areas using "fill". Visually it looks nice, but sometimes having several large patches of GND can give worse results. Often on a 2 layer PCB your best option is to route a couple GND traces together with the signals. Best results come from keeping the loop of the signals and its GND return current path as small as possible.

One very simple thing you can do is add resistors to the SCLK and MOSI signals, where the resistor is close to Teensy's pin, before the signal connects to the "long" wire(s) that go to the SPI chips. Usually 100 ohms is a good starting point. A more extreme approach is signal buffer chips and resistors at each buffer output, so each wire is driven separately.
 
Back
Top