SPI Basics
The other big communications protocol between integrated IC’s is SPI. It is usually pronounced “spy”, and it is the cool sounding synchronous protocol (as opposed to the awkwardly spoken I2C). If you are not familiar with I2C you can check it out in the previous portions of the tutorial. It might be a good idea since there are many comparisons and similar concepts involved between both protocols.
With respect to the overall pictures, it is used in a similar fashion to the I2C. However, there is no set protocol written on top of the physical layer. What I mean by this is that for example, in I2C, access to the registers almost always follows the order:
1. Chip address with read/write
2. Device address
3. Read/write data
So according to this protocol, you are basically limited to 127 devices, and a memory device address space of 256 (remember that 1 bit in the chip address byte is used for read/write, and the device address is one byte wide). In SPI, there is no set order on how the data is accessed. This allows for protocol abuse! What I mean by “abuse” is that, if I am creating my own SPI interface in an FPGA or ASIC, I can set up the data access in any which way I want. I can have the memory address width to be 8 or 16 bits for example, and set the data width to be 8 or 16 or even 32 bits. Generally you will find that each device type on the market has a similar access style. For example SPI EEPROMs from Atmel and Microchip are usually both accessed in the same way; however, they will differ significantly when accessing an ADC type IC with a SPI interface.
In Comparison to I2C
There is a big discussion as to when to use I2C and when to use SPI. Given that many devices with similar functions are sold with either an I2C interface or a SPI interface, which device should I choose? Well the answer can depend on many factors. Generally, I like to get the most results for the least amount of work (don’t we all?). I will usually choose a device for which I am familiar with, or have drivers written already.
There is one big advantages going for the SPI protocol. It is fast. Any times you have a large amount of access, for example storing/retrieving a large table, I prefer to use SPI. The protocol usually allows up to 10Mb/s whereas the I2C usually tapers out at around 400Kb/s. There is also less protocol overhead as you will see later. However, this speed comes at a cost. You will usually need to use 3 individual traces to connect the devices together, with one additional trace for each device. This means that for a system totaling 5 peripheral devices in addition to the microcontroller (which is not uncommon) you will need 3+5=8 individual traces. The implication is that using SPI up pins on the microcontroller as well as the real estate needed to connect the devices on the PCB itself. I2C requires only 2 traces and 2 pins, regardless of how many devices are connected.
Physical Connections
Before any programming can begin, you need to create a circuit that contains all the necessary connections for the SPI protocol to work. In general, a master and multi-slave configuration looks like this:

As you can see, there are 3 common signals to all devices, as well as one device specific signal. SCLK is the serial clock given by the microcontroller. It is used by the slave devices to sample the incoming data and output the outgoing data. There are two data lines going to and from the microcontroller. These two lines can be named differently depending convention. From the microcontroller’s perspective, the data going out is called the SDO (master data out). From the peripheral perspective however, this is data going in (so be careful what you call in and out, because it is always coming out of something and going into something). For the data going into the microcontroller the complementary notation is used. SDI (master data in) denotes data from the peripherals to the controller, which happens to be data going out of the slave. To avoid any confusion the figure above is labeled MOSI (master out, slave in) or MISO (master in, slave out). Confused yet?
Unlike I2C, which selects the device according to the chip address in the first byte of a data packet, device selection in SPI is accomplished by the CSB/SS signal. The signal’s name is an abbreviation for “chip select bar” (CSB) or “slave select” (SS), but both denotes the same function. The signal is active low. When the signal for a particular device is lowered, that device is selected and considered active. Needless to say that because multiple output drivers are on the SDI line, the device outputs needs to be in a high-impedance state when their respective SS lines are high (please remember this when implementing SPI in an FPGA! Don’t say I didn’t warn you).
Timing
In my humble opinion, SPI timing is more confusing than I2C. The primary reason for this opinion is that there are many mode of operation that is available on the market. In addition, something happens on every clock edge (rising and falling). You need to make sure you have your device and controller configured properly. As with most things, the price paid for flexibility is time and frustration spent configuring devices. However the bus is easier to debug in most cases, mostly because all the signals are unidirectional (I2C’s SDA line is bi-directional, which makes it a bitch to debug).
Here is the timing diagram from Wikipedia’s website.

When configuring your microcontroller, there are usually two settings that you need to take into account: clock polarity and clock phase. Given these settings there are 4 possible outcomes:
CPHA = 0, CPOL = 0 – first bit starts as soon as SS is lowered, data sampled at rising edge, data changes on falling edge.
CPHA = 0, CPOL = 1 – first bit starts as soon as SS is lowered, data sampled at falling edge, data changes on rising edge.
CPHA = 1, CPOL = 0 – first bit starts on first clock edge, data sampled at rising edge, data changes on falling edge.
CPHA = 1, CPOL = 1 – first bit starts on first clock edge, data sampled at falling edge, data changes on rising edge.
Different vendors will use different timing, so aware when looking at the datasheet. This datasheet from a microchip SPI EEPROM can serve as an example.

I can see that the first bit is already active even before the first clock edge. Also the data changes on the falling edge and is sampled at the rising edge. In order to communicate successfully with this device, I will need to configure my SPI module to CPHA = 0, CPOL=0. Depending on the microcontroller you are using, there might be different names to these clock configurations, but the general concept is the same. In Microchip’s PIC24 series, these configurations are called CKE and CKP.

That is the general overview of the protocol; the next section will deal with configuring the PIC24 and some subroutines.