Serial Peripheral Interface

Serial Peripheral Interface

Introduction

This is a basic description of the operation of the Serial Peripheral interface bus (SPI for short). SPI is a common serial communication protocol used to communicate between two or more digital devices. Follow the red tab on the right for a more in-depth examination of serial communications.

Basic Theory

SPI is one of many serial protocols, and like most, it is a master slave protocol. Master slave means that when two devices are communicating over SPI, only one device will initiate the transmission (regardless of sending or receiving data). SPI requires four different signals to function (only three if communication is uni-directional). These signals are:

  • MOSI: The Master Out Slave In signal is the line through which the master device transmits data to the slave device.
  • MISO: The Master In Slave Out signal is the line through which the master device receives data from the slave device.
  • SCK: Serial Clock is a clock signal from the master device that tells the slave device when to capture (and/or transmit) data.
  • SS: Slave Select enables the slave device's SPI interface (where enable is LOW and disable is HIGH).

Figure 1 shows a simple timing diagram of a typical SPI transmission. When the master device wishes to transmit data to the slave device, it will pull the SS pin LOW to initiate the transmission. Once the SS is LOW, the master device will then send a clock signal on the SCK pin. Given that SPI is in mode 0 (more about modes towards the end of this document), the master device will set up data on the MOSI pin so that it is valid on the rising edge of the SCK signal.

Figure 1. Example of a SPI transmission.

Slave devices in turn use a shift register to capture and shift the data from the MOSI line on the rising edges of the SCK signal. If the slave device needs to transmit data, then it would send the data on the MISO pin. The data's bits are sent on the falling edge of the SCK, so that the data would be stable when read by the master on rising edges of SCK (given that you're still operating in mode 0).

If data is both being sent and received, then (like in Fig. 2) data from the master device is being shifted out on the MOSI pin to the slave device, and data from the slave device is being shifted back in through the MISO pin to the master device and into the same registers.

Figure 2. SPI shift registers.

Modes in SPI simply refer to the polarity of the SCK signal and the phase in which data is read. Polarity in this context meaning if the clock signal is normally held low when not transmitting, and toggled high to transmit (or the opposite, normally high and pulled low to transmit). Phase in this context is simply whether data is read on the rising edge of SCK and setup on the falling, or the opposite.

  • Mode 0: SCK signal is normally held low. Data is read on the rising edge and setup on the falling edge of the SCK.
  • Mode 1: SCK signal is normally held low. Data is read on the falling edge and setup on the rising edge of the SCK.
  • Mode 2: SCK normally held high. Data is read on rising edges and setup on falling edges.
  • Mode 3: SCK normally held high. Data is read on falling edges and setup on rising edges.

SPI and MPIDE

In MPIDE there is a built in library to handle low level SPI functions, you simply need to include “SPI.h” in your sketch. It is important to note that SPI signal pins are dedicated to specific pins on chipKIT boards. On some chipKIT boards you may also need to set a jumper block on the board to enable the SS pin signal (consult your board's reference manual for exact pin-outs and block numbers).

Like the Serial object, SPI is initialized in the setup function with:

  • SPI.begin()

SPI can also be additionally configured by the following methods:

  • SPISetBitOrder(): Sets whether the most significant bit or least significant bit is transmitted first (using the parameters LSBFIRST or MSBFIRST).
  • SPISetDataMode(): Sets the SPI modes described above. Without being called, SPI defaults to mode 0. (The parameters for this method are SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3).

  • SPISetClockDivider(): Sets the SPI transmission speed by specifying the divisor of a 16 MHz base clock (specifically for the Uno32™). For example, if the max speed a slave device could communicate was at 4 MHz, then SPI_CLOCK_DIV4 could be used to divide the base clock by 4 to get a 4 MHz transmission rate. (The parameters for this method are SPI_CLOCK_DIV2, SPI_CLOCK_DIV4, SPI_CLOCK_DIV8, SPI_CLOCK_DIV16, SPI_CLOCK_DIV32, SPI_CLOCK_DIV64, SPI_CLOCK_DIV128.) Without being called, the default clock division divisor is 4.

Data in SPI is then simply transmitted by toggling the SS pin (i.e., pulling LOW to activate a transmission, or HIGH depending on the specific device you are communicating with), and calling the SPI.transfer() method. After data is transmitted, toggle the CS pin to signal the end of the transmission.


  • Other product and company names mentioned herein are trademarks or trade names of their respective companies. © 2014 Digilent Inc. All rights reserved.