• To drive multiple SPIs, you need multiple NSS (negative serial select) pins, which you can and usually do specify in the .send() and .write() so you do not have to do some extra code to pull the NSS pin low (negative) before the transmission and push it back up high after transmission for devices that need it. Espruno (= @Gordon) made this so simple that you can use an array and nss as parameters to avoid having to push and pull the NSS yourself, even for multi-segmented transmission. If you cannot - or do not want to go with an array or for what ever reason want to control NSS at your terms, you pull it low before the transmissions, transmit without nss parameter, use nss parameter with the last transmission, or separately after last transmission without nss parameter. Having the NSS(s) on portexpander ports works well, because there is not really a time constraint from pulling it low to the begin of transmission and from the end of transmission to pulling it up high again. SPI even allows you to interrupt a current transmission for handling something more important or pressing and then resume transmission. For interruptions you need though another line, which is usually called NHOLD - negative hold. SPI devices for mass data - such as SPI driven memory (FRAM/MRAM/SRAM/EEPROM) - have usually this NHOLD implemented (see, for example, FRAM Ferroelectric RAM as used in the conversation about 256-Kbit (32 K × 8) Serial (SPI) F-RAM - Ferroelectric RAM - SPI challenges). (FRAM is like FLASH EEPROM but without EEPROMs' drawbacks: no wait after write and no erase of pages to write again. It is like non-volatile RAM that holds data without having to be powered. TI uses it in some of their micro controllers which make a save before hibernate or power fail a non-event / obsolete. Btw, the FRAM application code uses a combination of separated and .send() / .write() integrated NSS handling (multi segment transmissions consists of send command, send address, send/receive data byte(s)...).

    If you run out of pins, you can use a portexpander on SPI - or, if you still have a few pins to play with - use a plain 3-to-8 Line Decoder (74HC138) - to drive the NSS, NCS (Negative Chip Select) or what-ever-(time-uncritical)-control lines. The 74HC138 has even 3 'Enable' lines - 1 ENABLE and 2 NEGATIVE ENABLE for easy cascading: 4 pins control 16 NSS with simple digital write.

    Minimal number of control ports and wiring aren't the only reasons to pick a portexpander solution: (especially MCP23017) portexpanders have good interrupt support to minimize amount of code to execute to get the job(s) done. For less demanding applications, you can use SNx4HC595 8-Bit Shift Registers With 3-State Output Registers as demonstrated in conversations about Driving LED matrix with shift registers such as 74HC595 and Retro Bubble Displays driven with 74HC595.

    You can use up to 8 SPI connected MCP23017 portexpanders without spending any extra pin: you just connect the MCP23017 portexpanders' A0..A1 pins accordingly to GND and 3.3V and supply the 'HAEN: Hardware Address Enable bit' bit as 1 and portexpander address A0..A2 in the command byte to address the portexpander you want to talk to. There is practically no limit when using (cascaded) portexpanders: one portexpander you use to control the address lines (dynamically).

    So far about SPI. I2C is not much different then that all goes solely over hardware control lines and no chip/device address information data in the commands. Even with a puck that has very limited pins (and pads) as ports exposed, you can run a multi SPI and multi I2C configuration... Most likely you will run out of processing power before you ran out of addresses.

About

Avatar for allObjects @allObjects started