One of the issues with the Serial Peripheral Interface (SPI) bus, as many people have noted, is that it requires one Slave Select (SS) line – which means one GPIO pin on your microcontroller – for each device on the bus. That’s in addition to the three main bus lines – MOSI, MISO and SCK.
This might be difficult on a microcontroller with lots of other things to connect to. But there are ways of getting around this.
You could, for example, use the I2C interface to run a port expander chip: an MCP23017, would give you 16 additional GPIOs (at the expense of some speed) and still leaves the I2C bus usable for other things. Even if you don’t need I2C for other stuff, you only tie up two GPIOs.
But there’s a risk with that approach. The way that SPI works is that the MOSI, MISO and SCK are common to all slave devices on the bus. You choose which device the master talks to by taking its dedicated SS line low. The key here is that only one slave device should be selected at any one time. With a port expander, there’s always a risk that an oversight in your code might result in two or more devices being active at once. The result of this is probably best covered by the term ‘undefined behaviour’.
When I wrote my introduction to SPI, a Reddit user going by the name ‘spainguy’ mentioned that 74xx138 decoders can be useful for adding SS lines. I hadn’t thought of this but it is a good solution.
We’ve met these decoder chips before, when I talked about decoding the 64KB address space on my (not progressing very quickly) 6502-based computer project. Essentially, it goes like this. The 74xx138 has three input lines, A, B and C. These are binary inputs, effectively representing the values 1, 2 and 4 (and 0 if they are all off). Combinations of inputs on these three lines therefore give you eight possible values in the range 0-7.
This value is placed on the eight output pins Y0-Y7. By default (and if the input value is 0) all the output pins are high. But if one or more of the input lines goes high, the output pin representing that value goes low.
Let’s say that input pin A (representing 1) and input pin C (representing 4) are both taken high. This gives a value of 1 + 4 = 5. That means Y5 would go low and all the other output pins would remain high.
On the 74xx138 only one output can be low at any given time. On most ICs, the pin that makes it active – variously called Chip Enable (CE), Chip Select (CS) or, in the case of SPI, Slave Select (SS) – is ‘active low’, so the 74xx138 is the perfect way of selecting between up to eight SPI devices.
The 74xx138 will require three GPIOs on your microcontroller, but in return you get to control eight devices. It’s a good way of getting more bang for your buck from your GPIOs. And it’s not just for SPI – there are all manner of other ICs and devices that require a line to go low to activate them. Thanks for the tip, spainguy.