SPI and Synchronous Serial
SPI is a particular type of synchronous serial. We'll start by discussing the characteristics of synchronous serial.
Serial vs. Parallel
Serial (as opposed to Parallel) means one bit (1 or 0) is placed on the bus (wire or wires) at a time.
Synchronous serial vs. Asynchronous serial
When we talked about asynchronous serial, recall that the receiver was responsible for figuring out exactly when a bit should be read from the bus. To do this we used a timer, and kept track of how much time had elapsed. At certain time intervals, we would record what was on the bus.
With synchronous serial, things are more straightforward. We are explicitly told when we should read the data line. To do this another wire is added (for a total of 2 wires). This other wire, called the clock line, tells us when to read the data line.
How the clock line tells us when to read the data line
There are several ways in which the clock line could tell us when to read the data line. For example, maybe we should read the data line whenever the clock line is a logic 1. A better way is to use the "edge," or "transition" between logic states to indicate that the data line should be read. This has the advantage of being a single event -- a single snapshot in time -- rather than a region of time. This reduces any ambiguity about when exactly the data line should be read.
Rising edge or Falling Edge?
The rising edge (also called positive edge, or posedge) is when the state changes from a low to a high (o to a 1). The falling edge (also called negative edge, or negedge) is when the state changed from a high to a low (1 to 0). In SPI, data is only ever valid (should be read) on either the rising or falling edge. Which one it is - rising or falling edge - depends on the implementation. For existing parts and systems, you'll have to look it up (typically in a datasheet). In some applications you may have the flexibility to use either -- you'll need to pick one, and then make sure everyone sticks to the standard.
Synchronization - which bit belongs to which byte?
We know when to read a bit, but how do we know which bit we are reading? In other words, how do we synchronize? The most straightforward way to synchronize is to use a 3rd wire. Ahead of time, we decide that a rising (or falling) edge of that wire will be our synchronization event. Typically this wire is called enable (or reset, but it's the same idea.) It allows the different parts of a system to synchronize -- to revert to a known starting state.
Enable and Disable
The enable line is used for synchronization - but it usually also serves another purpose. Its state (0 or 1) indicates if something should be enabled or disabled. For example, maybe you don't need a particular device to be running all the time. You may be able to disable it, putting it into a low power mode. In SPI, this has the added benefit of choosing which device you want to talk to. You simply disable all the devices except the one you want to talk to.
A simple implementation of synchronous serial -- the Shift Register
In practice, shift registers are often used in the implementation of SPI.
Point to point connection
There are many possible ways in which synchronous serial could be used with more than two devices. One simple way is that each pair of devices that needs to communicate has dedicated connections. Notice however, that the number of connections you need grows geometrically. So this isn't a great solution.
A bus is a collection of wires, shared by many devices. Notice that a bus uses far fewer connections. However there are some limitations:
- Only one device can "talk" at a time
- If two devices talk at a time, this is a "bus collision". Imagine what happens if one device outputs a 0 at the same time as another device outputs a 1. This is a short circuit!
- A device needs some way of knowing is someone is already talking on the bus
- The bus needs to recover from potential conflicts, and have a way to figure out who gets to go first
While a bus topology like the one shown is very powerful, it requires electrical and protocol-level complexity to deal with the issues raised above. It's not ideal for very cheap and simple devices.
The SPI way
SPI uses a bus, but makes a few compromises to make things very simple.
Only one master
In SPI, only one of the devices is in charge. It alone decided who can on the bus. Furthermore, devices can only talk to the master device, they can't talk to each other.
The lowly slaves
All other devices on the SPI are called slaves.
Choosing which Slave gets to talk with the Master
In SPI, the master uses an enable line for each and every slave. In this way the master can select which slave is active. Generally speaking only one slave can be active at a time.
SS or EN
In SPI, the enable line is usually called SS (slave select) or EN (enable). It's all the same thing.
Enable (EN or SS) is active low
The SPI enable line is almost always inverted: 1 means disabled, and 0 means enabled.
Communications with the active slave
In SPI, the master has a dedicated data output line, called MOSI (master out, slave in). All the slaves listen on this line, but ignore it if they are not active. In SPI, data is typically sent most significant bit first. (MSB first)
The master also has a dedicated data input line, called MISO (master in, slave out). Only the active slave is allowed to transmit on this line. All the other slaves MUST transition to high-z mode when they are not active - i.e. they may not drive the line. This is the function of a tri-state buffer. In SPI, data is typically sent most significant bit first. (MSB first)
Since this is synchronous serial, there needs to be a clock, which is typically called CLK. The clock is used with both the MOSI and MISO data lines.
The unspecified details
SPI leaves a couple things unspecified. For sample, should a slave read the MOSI line on CLK's rising edge, or its falling edge? An additional complication is that the slave must generate output data on MOSI, such that it data will be valid when the master reads it in accordance with its own CLK signal. This is a little backwards.
Clock polarity and phase - CPOL and CPHA
Datasheets specify the previously mentioned details in terms of clock polarity (CPOL) and clock phase (CPHA). An additional complication is that the slave must generate output data on MOSI, such that it data will be valid when the master reads it in accordance with its own CLK signal. This is a little backwards. Clock polarity (CPOL) is the state of the clock at the moment a slave's enable line becomes active. CPOL=0 means that the clock is low (0) as the slave becomes enabled. CPOL=1 means the clock is high (1) when the slave becomes enables. At some point after a slave becomes active, the clock like will change. If the data on MOSI and MISO should be read on this first edge, the Clock Phase (CPHA) is 0. Alternatively, if data on MOSI and MISO should be read the 2nd time the CLK changes, the Clock Phase (CPHA) is 1. CPOL=0 (the clock starts out low) CPHA=0 (data is valid on the 1st clock edge) CPOL=0 (the clock starts out low) CPHA=1 (data is valid on the 2nd clock edge) CPOL=1 (the clock starts out high) CPHA=0 (data is valid on the 1st clock edge) CPOL=1 (the clock starts out high) CPHA=1 (data is valid on the 2nd clock edge)
SPI Variations / Settings
Clock Polarity & Clock Phase
The SPI variations you'll typically need to worry the most about is the clock polarity and clock phase discussed above.
The bit rate is the fastest speed the CLK line will operate at. This can vary wildly with the application, from a few hundred bits per second, to many tens of MHz. Since the CLK line provides us when to read the data line, there is no significant difference in how things operate, assuming all the devices can keep up.
Data is sent over the SPI most significant bit first. However, you may find yourself using SPI code or a SPI hardware peripheral with synchronous serial that isn't strictly SPI.
Bits per transfer/word
In most applications data sent over and SPI is byte oriented. However, there is no fast rule in this area, so technically any number of bits could comprise a word. SPI synchronizes using the Enable (or SS) line - there is no delimiter to specify when one word ends and the next begins.
Enable/Slave Select polarity
SPI applications typically use logic 0 as the active state for the enable line. For synchronous serial more generally, this could easily be the other way around.
Some Good Resources
Example Parts That Use SPI
trello ID: 57215d3ec98d346dc5380dd3