SPI, or Serial Peripheral Interface (see also my previous post) is characterized by a
master-slave architecture and, contrary to I2C or UART, doesn't have an official standard, so you have to check with the device manufacturer for the spcifications (for example, here's the Arduino documentation on the subject)
Connection is done using 4 wires; these are the most used pin naming conventions:
- MOSI (Master Output, Slave Input), Master --> Slave
- MISO (Master Input, Slave Output), Slave --> Master
- SCK or SCLK (Serial CLoCK), Serial Clock Line
- CS or SS (Slave or Chip Select), activates the slave
When starting a communication the Master configures the CLOCK (in a frequency supported by the device of course) than selects the device to communicate with using the SS line, by setting it to LOW
Many devices use a 3-state logic, i.e. another value other than LOW or HIGH, which is Z, or high impedance state, that makes the device "disappear" in the eyes of the master and, in all effect, have no influence on the connections; it's important when we have multiple slaves and we don't want influences or commands to/from other peripherals.
During a clock cycle the master can perform a full-duplex data transmission with the slave, as we can see in this awesome animation from AllAboutCircuits:
Transmission is unsing done with an 8-bit size, by using 2 shift registers connected in a virtual ring configuration (one in the master, the other in the slave). On a clock edge both master and slave shift out a bit, outputting it on the transmission line, and on the next cycle each devise samples the transmission line and set a new least-significant bit on their shift register, thus exchanging register values.
Besides the frequency we need to consider also the Clock Polarity, CPOL - if the clock idles HIGH or LOW and Clock Phase - CPHA, determines when data is transmitted relative to the clock:
CPOL = 0 : clock idles at 0, each cycle is a pulse of 1 (the leading edge is a rising edge, and the trailing edge is a falling edge)
CPOL = 1 : clock idles at 1, each cycle is a pulse of 0 (the leading edge is a falling edge, and the trailing edge is a rising edge).
CPHA = 0 : a half cycle with the clock idle, followed by a half cycle with the clock asserted.
CPHA = 1: half cycle with the clock asserted, followed by a half cycle with the clock idle.
Based on the clock polarity and clock phase, there are four combinations, or modes, that can be used: if the clock phase is 0, the data is latched at the rising edge of the clock with polarity 0 and at the falling edge of the clock with polarity 1. If the phase of the clock is 1, data is latched at the falling edge of the clock with polarity 0 and rising edge with polarity 1.
Image from https://openlabpro.com/
There can be different configurations for SPI connected devices:
Single Master Single Slave
This is the easiest configuration, of course; in this case the CS pin on the slave device is alwaus grounded.
Image from best-microcontroller-projects.com
Independent slave configuration
Probably the most common configuration, uses an independent Select Line for each slave, while the master activates only one chip select at a time. If the Master doens't have enough CS pins to manage all the slave we can use a multiplexer chip.
An advantage of this scheme is that you can control each device separately, allowing for connection of devices that require different clock schemes - in which case you can re-program the master SPI hardware module before enabling a specific CS so each slave understands the relative signal.
Note that in case of multiple slaves the MISO pin is shared, so we need connected devices that can work on the 3-state logic mentioned before (also, pull-up resistors must be used to avoid floating) since the slaves wich are not selected need to have an high-impedance output applied (if the device doesn't suport it a 3-state buffer chip must be used)
Image from Wikimedia Commons
Daisy Chain configuration
So called because multiple devices are wired together in sequence or in a ring, much like a garland of daisy flowers.
In this configuration data is shifted out of the master into the first slave, from the first slave to the second and so on until the last slave, which uses its MISO line to send data back to the master.
The SPI port of a s slave is configured to receive data on the first group of pulses and to send out an exact copy of data on the second pulse; each slave copies and transfer data until the single CS line is brought HIGH by the master.
Image from maximintegrated.com
For further readings the [Wikipedia entry](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface) goes deeper and gives a long list of pros/cons of this communication protocol.