Serial Peripheral Interface (SPI)
Programming for SPI
Many microcontrollers have built-in SPI peripherals that handle all the details of sending and receiving data, and can do so at very high speeds. The SPI protocol is also simple enough that you (yes, you!) can write your own routines to manipulate the I/O lines in the proper sequence to transfer data. (A good example is on the Wikipedia SPI page.)
If you're using an Arduino, there are two ways you can communicate with SPI devices:
You can use the shiftIn() and shiftOut() commands. These are software-based commands that will work on any group of pins, but will be somewhat slow.
Or you can use the SPI Library, which takes advantage of the SPI hardware built into the microcontroller. This is vastly faster than the above commands, but it will only work on certain pins.
You will need to select some options when setting up your interface. These options must match those of the device you're talking to; check the device's datasheet to see what it requires.
The interface can send data with the most-significant bit (MSB) first, or least-significant bit (LSB) first. In the Arduino SPI library, this is controlled by the setBitOrder() function.
The peripheral will read the data on either the rising edge or the falling edge of the clock pulse. Additionally, the clock can be considered "idle" when it is high or low. In the Arduino SPI library, both of these options are controlled by the setDataMode() function.
SPI can operate at extremely high speeds (millions of bytes per second), which may be too fast for some devices. To accommodate such devices, you can adjust the data rate. In the Arduino SPI library, the speed is set by the setClockDivider() function, which divides the controller clock (16MHz on most Arduinos) down to a frequency between 8MHz (/2) and 125kHz (/128).
If you're using the SPI Library, you must use the provided SCK, PICO, and POCI pins, as the hardware is hardwired to those pins. There is also a dedicated CS pin that you can use (which must, at least, be set to an output in order for the SPI hardware to function), but note that you can use any other available output pin(s) for CS to your peripheral device(s) as well.
On older Arduinos, you'll need to control the CS pin(s) yourself, making one of them low before your data transfer and high afterward. Newer Arduinos such as the Due can control each CS pin automatically as part of the data transfer; see the Due SPI documentation page for more information.
Interested in learning more foundational topics?
See our Engineering Essentials page for a full list of cornerstone topics surrounding electrical engineering.