Past articles in the NetBurner Learn Blog have introduced several serial protocols. Some of those protocols (RS232 and RS485 and RS422) are intended for communication via cables between systems across moderate distances. As you may know, NetBurner provides solutions for extending those point to point protocols to function between devices anywhere on the planet.
We’ve also introduced you to the I2C protocol, intended for point to point serial communication among devices within a single system, usually on a single PCB or within the same box. In today’s blog, we’ll consider another “on-board” serial protocol, the Serial Peripheral Interface, or SPI.
Why use an on-board serial protocol?
Our lead-in quote from Woody Allen offered his amusing insight into the underlying purpose of time. Similarly, serial hardware device interfaces like I2C and SPI have an underlying purpose; they offer the benefit of simpler hardware if you can afford more time to transfer data. Paraphrasing Woody, “Serial busses are an engineer’s choice when everything doesn’t have to happen at once.” When designing a complex hardware system, this often turns out to be a desirable tradeoff.
Consider for example the circuit traces and logic chips that might be required to access a conventional four-megabyte memory. A memory that large requires 22 wires to specify a memory address, and eight or more wires to transfer the data, depending on word size. The system design may additionally require several clock and control lines, as well as buffer and bus latch devices for holding data as it is transferred between chips.
Microcomputer systems developed in the last quarter of the 20th century, such as S-100, VME, and PCI, employ wide, parallel busses in order to accelerate processing. While this many-wire, multiple device complexity may be important to achieve high speed in a computer system, it is generally not necessary in a modern embedded IoT device. Using a serial bus (like I2C or SPI) can reduce the 30+ wires of our memory example to just a few.
Simpler Large Memory SPI Schematic for this Embedded IoT PCB
The History of SPI
The SPI standard was created by Motorola in the mid 1980’s, not long after the I2C bus was invented by Philips. SPI rapidly became a de-facto standard. Because of its benefits and utility, it has been widely adopted by industry. And, although the closest thing to a formally published, agreed upon standards document is this out-of-print ‘SPI Block Guide’ datasheet from Motorola, SPI has been uniformly interpreted and implemented with only slight variations by many different companies. A large and still growing number of devices exist and are available for incorporation into IoT devices and other embedded systems.
SPI Functional Overview
An SPI System with a single slave
The SPI master uses at least three output lines to control the bus: one for data (MOSI—Master Out Slave In), one to clock the data (SCK—Serial Clock), and one each to select the slave it wishes to interact with (*SEL—Slave Select). The slave device accepts master control and responds by putting data on its single output line (MISO—Master In Slave Out).
Master and Slave form a circular shift register
This diagram illustrates how an eight-bit transfer of data between a master and a single slave device works. Although the diagram pictures an eight-bit transfer, the SPI protocol doesn’t specify any particular number of bits. The transfer size is entirely up to the device implementation. The system designer must carefully read device spec sheets in order to understand and program for the number of bits being transferred in an SPI operation.
In this example, once the *SEL has been asserted (i.e. pulled LOW) by the master device, the master will drive the clock and data lines like this:
Clocking (Assumes device already selected. View of one byte worth of outgoing bits.)
Notice that the master sets MOSI before SCK because data is transferred on the rising edge of SCK (dotted lines). Note also that because *SEL, MOSI, and SCK are completely under the master device’s control, they need not be “regular” (as illustrated in this diagram). In other words, the length of the clock pulses can be arbitrary. This makes it entirely possible to “bit-bang” an SPI master device, because the master governs the interface timing completely with the outgoing lines.
An SPI System with multiple devices
SPI systems can include an arbitrary number of Slave devices. However, each Slave device must have its own separate select line. Here’s a diagram illustrating how multiple Slaves may all be interconnected on the three common SPI Bus lines, but each must have its own *SEL line.
In a multi-slave system like this, only one slave device at a time is selected by the master and actively in operation.
The SPI Bus supports an arbitrary number of slave devices
An alternate SPI configuration
An alternate SPI Bus configuration: the Daisy Chain
In a less used, but definitely possible configuration, a system designer may choose to daisy chain SPI devices. Note that this only works if the devices and their specific operating protocols are designed with daisy chaining in mind.
In a daisy chain configuration, data originates with the master device as usual, but is then shifted sequentially through all the slave devices. As illustrated here, all slaves are selected simultaneously, with each slave feeding data to the next slave in series, until data finally returns to the master device from the last slave’s MISO line.
Because one *SEL line enables all slaves, daisy-chain wiring is a little simpler. The master also gains some insight into whether all devices are working, because data must pass through every slave in the chain before returning to the master. Of course, software on the master device must be aware of the length and purpose of the entire shift-chain and its associated slave devices. The devices themselves must be intended for this sort of SPI setup.
For the curious, here is an application note with a detailed example showing three analog to digital converter (ADC) chips daisy-chained on a common SPI bus. The appnote explains that the design of the ADCs in this example incorporates particular characteristics supporting the daisy-chain configuration.
For comparison, here is another application note explaining the operation of another manufacturer’s motor controller chips daisy-chained on a common SPI bus. Once again, the chips in this example incorporate features to support daisy-chaining.
An example of SPI device operation
Here’s an example of how a real-world SPI device operates. The following timing diagram is taken from the datasheet for an SPI memory device. The operation depicted is a memory read.
As always, the operation begins with the master asserting *SEL (here labeled *CS, or “NOT Chip Select.”)
The master then begins transferring data required by the device out via MOSI (here labeled simply SI). One bit of data is shifted out as the master asserts each SCK pulse.
In this example, the master must transmit an eight-bit READ Opcode (0x03) followed by the sixteen-bit address of the desired memory content. Having received that information, the memory device then begins shifting data out on the MISO line (here labeled simply SO).
If the master continues clocking the device, as many bytes of data as desired can be read out of the serial memory, one byte after another, without needing to re-issue a READ Opcode or further memory addresses.
Spy vs Spy? No, I2C vs SPI
In contrast, SPI bus lines are actively driven both low and high. This hardware difference makes SPI bus level transitions sharper and less susceptible to interference from electrical noise. The SPI bus also consumes less power than I2C because it only draws current when data is being transferred.
I2C wins this round in the wiring simplicity category, but SPI wins in the noise immunity and power consumption categories.
SPI wins this round, because to address a particular device, it simply lowers the device select line. This simplicity also gives it an edge in our next category.
I2C is inherently a half-duplex protocol, that is, data can only travel in one direction at a time. Because the I2C bus floats between messages, time must be allowed for the pull-up resistors to return the bus to a high level. Because all control is “in-band,” the I2C protocol has much more overhead than SPI. These three significant differences make I2C relatively much slower than SPI.
Variations On A Theme
A detail of lesser importance, but one to be aware of, is that there are four “modes” that SPI can run in, labeled Mode 0, 1, 2, and 3. Many descriptions of the SPI protocol will try to “snow” you and make this seem complicated; it isn’t, really. These “modes” are simply alternate ways the clock can work.
The clock can have one of two polarities (CPOL 0 or 1) and one of two phases (CPHA 0 or 1).
A clock CPOL=0 means that the clock idles at 0. An SPI cycle is a pulse to a level of 1, with a rising and falling edge. A clock CPOL=1 means that the clock idles at 1. An SPI cycle is a pulse to a level of 0, with a falling edge followed by a rising edge. Note that, in both cases, there is a leading edge and a trailing edge of the clock pulse as it changes from its idle state to an active state and back again to the idle state for that polarity.
When CPHA=0, data outputs are changed on the trailing edge of the clock and data is read on the leading edge. In contrast, when CPHA=1, data outputs are changed on the leading edge of the clock and data is read on the trailing edge.
Like any binary options, two options (CPOL and CPHA) with two possible states each (1 or 0) result in four possible modes. SPI Mode 0 is by far the most commonly used mode, but don’t stress over this; just check your specific device datasheet(s) to find which mode the device is designed to operate in, and set up your software parameters to match.
Operating details differ on a device by device basis, depending largely on the manufacturer’s choices. We’ve seen one example in the READ Waveform of the Atmel/Microchip memory device. If you read that datasheet, you’ll discover other opcodes and sequences for WRITE and other operations specific to that device. Each datasheet for each particular device in your design should have those details available to you.
As a system designer, getting an SPI system up and running will ultimately mean carefully studying the individual datasheets, and then writing or configuring your SPI software driver and debugging your code in a working system. NetBurner products, such as the MODM7AE70, typically give you a “leg up” in this regard by providing at least a baseline SPI driver to begin working with and examples that illustrate how it works.
Conclusion: Deciding Between I2C and SPI
So, how do you choose between these two busses? Sometimes it boils down to the particular chips you need for your design. You may only be able to find the device function you need in one or the other of these flavors.
Be sure to carefully read the datasheets for devices you need, and consider the clock rates and power consumption. How fast does your design need to be? How many devices do you need in your overall system?
Sometimes cost is a factor. Especially when you’re designing a high-volume product, a few cents difference in price between two otherwise comparable devices can amount to tens of thousands of dollars in mass production.
- I2C — “Inter-Integrated Circuit” or “I Squared C,” An In-System Serial Protocol
- SPI — “Serial Peripheral Interface,” an In-System Serial Protocol
- SCK — Serial Clock
- MOSI — Master Out Slave In – sometimes also simply ‘SI’
- MISO — Master In Slave Out – sometimes also simply ‘SO’
- *SEL — “NOT Select,” an SPI device select line
- *CS — “NOT Chip Select,” an alternate legend for *SEL
- CPOL — SPI Clock Polarity (0 or 1)
- CPHA — SPI Clock Phase (0 or 1)
- SPI Mode — 0, 1, 2, or 3 – defined by combined states of CPOL and CPHA
- IoT — “Internet of Things,” i.e. small, network-connected embedded systems
- Tri-State — A signal that can be high, low, or floating De-Facto Standard — A widely accepted design standard that “just happened”
- Bit-Bang — Use software to execute a serial protocol, one hardware line at a time