16 SPI devices? Is it possible?

Status
Not open for further replies.

sandalhat

Well-known member
Hello all,

I have been doing some digging on this topic with mixed results. I hope to have 16 SPI devices controlled by one Teensy 3.2. Initially I planned to use a 16 channel analog mux/demux to select between my devices (using 4 DIO pins to manually address the devices) and define CS to be the same pin for all devices I'd be using, which is then connected to the signal input of the demux. All the outputs of the demux would be pulled high so that only one CS could be active at a time. I expected some settling time when switching between addresses/channels, which is fine because although I will update all 16 devices in short succession, I won't be doing much interacting with each device, I won't be updating them often (most of the time there will be no activity on the SPI bus), and timing of the group update isn't critical.

I can't really find a good source saying this is definitely possible or not possible, just suggestions of each case being true. Is the internal resistance of the mux/demux a problem? It seems like logic low will still be achieved when the Teensy pulls the signal pin low. Is the response time of the signal going low to the output going low going to mess up any devices' timing?

Is it a better idea to use a 4 to 16 decoder? I already have the mux/demux so I'm hoping that will work but I'm not sure. I will probably be testing this as soon as I have a chance but I'm looking for some feedback before I go too far down this road thinking that it's possible if it isn't. Thanks in advance!
 
Four GPIO bits fed to a 4 to 16 logic level decoder chip. Now you have 16 chip select signals, all mutually exclusive. The switching time would be super fast.
That decoder chip needs to have an Enable which you set true after changing the 4 bit code sent to the GPIO bits. Then set the Enable false after the SPI transaction is finished.
I suppose you should figure out how to output all 4 GPIO bits simultaneously, but altering them in four successive I/O lib calls is slower but OK so long as the Enable is false.

Hmm, I guess using the same chip select for all 16, when calling the SPI library is OK, as long as you output the 4 GPIO bits before calling the SPI library. The SPI library will still assert the GPIO bit passed to it, so maybe that bit is a GPIO port bit that you "waste".

You should read about and use SPI Transactions if that one SPI port (MISO/MOSI/CLK) is to be used with your SPI devices AND some other SPI device. This allows the SPI port to be "time shared".

If you could find 16 GPIO bits to use, this would be much easier, of course.

Or maybe your 16 things can also use I2C and you don't have the chip select hassles.
 
Last edited:
You could also use an i2c I/O expander (eg. MCP23017) to get 16 digital outputs to use as SPI chip selects.
 
If your SPI clock rate is high, make sure to have your data lines short. 16 devices sharing high speed lines becomes more difficult with any line length. As it is, there will be a higher than normal capacitive load since each device adds together.

By the way, the Teensy 3.x has selectable I/O drive strength, but I am not sure which setting is most appropriate for a heavily loaded bus. When unloaded, in the (non-default) high-speed drive setting I measured sub-nanosecond rise times from Teensy 3.1, about 10x faster than in the normal configuration https://forum.pjrc.com/threads/2873...ed-on-Teensy-3-1?p=75044&viewfull=1#post75044
 
Last edited:
Thanks all for the information, I appreciate it! I did a test last night with 2 RA8875 displays sharing CS through the analog multiplexer and it worked really well. I like the idea of the I2C I/O expander to save ports and also because my I2C bus will be pretty sparse for this project so I can get a little more use out of it potentially while not tying up as much I/O.

The wire lengths do concern me somewhat, but I'm anticipating using a tri-state buffer for all SPI lines for each SPI device (because I don't think any of the devices share SPI well otherwise). I'm hoping by placing these near the teensy I will mitigate this somewhat.
 
Thanks all for the information, I appreciate it! I did a test last night with 2 RA8875 displays sharing CS through the analog multiplexer and it worked really well. I like the idea of the I2C I/O expander to save ports and also because my I2C bus will be pretty sparse for this project so I can get a little more use out of it potentially while not tying up as much I/O.

The wire lengths do concern me somewhat, but I'm anticipating using a tri-state buffer for all SPI lines for each SPI device (because I don't think any of the devices share SPI well otherwise). I'm hoping by placing these near the teensy I will mitigate this somewhat.
Be sure to read up and know when/if to use the SPI Transactions library from PJRC.
 
Be sure to read up and know when/if to use the SPI Transactions library from PJRC.

Thanks, yeah I have been. All the libraries I'm using have implemented SPI transactions. I'm going to be getting one if each device type on a bus soon (3 types) to see if I can get them all working at once.
 
Sounds like this should work. Real logic chips will be better than the analog mux. You might need to use some buffers if the wires are long or have a lot of capacitance, to broadcast MOSI and SCK out to 16 devices. The RA8875 is one of the troublesome chips which doesn't tri-state its MISO output, so each RA8875 needs a tristate buffer chip anyway.

If you don't need the fastest SPI clock speeds, chips with slew rate control can really help reduce the noise from reflections and signal quality issues of long wires. Likewise, Teensy has slew rate limiting on its pins, which is disabled when using SPI. Writing to the pin config registers can turn it back on. Might help?
 
Adding to Paul's comments... since you're adding a chip or more, you could greatly reduce the risk by multiplexing the MOSI/MISO/Clock to go to/from only the connection affiliated with the corresponding chip select. If the wires are very short, like 6 inches, you might get away with a wired "star", but at higher speeds, it might well be a noisy arrangment.
 
Thanks for the new responses. Thank you Paul for posting on my question. Also thank you for making this all possible, what you are doing is incredible and I appreciate all your work!

I'll play around with the different approaches but it's good to know it's possible so I can work on figuring out the best option for my needs/usage.

I was planning on using a 74HC125 to isolate SPI lines for each device. I'm planning on these being close to the teensy to minimize wire lengths. As I understand it, only the wire runs on the teensy side of the buffers plus the wire run to the active device should matter for that device. I'm hoping that this will both solve the tri-state MISO problem (of course it does this much) and also reduce concerns about wire lengths for the entire bus. It will be less efficient in terms of cable routing but since I need the buffers anyway for my 15 displays (1 RA8875 and 14 ili9341) then I might as well attempt to solve 2 problems at once. I haven't tested whether or not I need it for the nrf24l01+ I want to use but at that point I might as well treat all 16 devices the same way.
 
You can use MCP23S17 that can share MOSI,MISO, SCLK and CS (yes! not an error!) between 8 devices by using HAEN technology. This let you use the SPI version of MCP23xxx as I2C but with SPI speeds. To have 16x16 devices you'll need 4 pin for GPO or 5 pin for GPIO.
To use with RA8875 you will need a complete 74hc125 isolation, internally RA8875 has pullups on MISO (as noticed by Paul long time ago) but also on SCLK and this interfere with other SPI devices so using an isolator will help.
 
Last edited:
Status
Not open for further replies.
Back
Top