Lab 7: Serial Peripheral Interface (SPI) Communication

This lab allows students to explore communication using the Serial Peripheral Interface (SPI) bus. Students will learn about the basic theory behind SPI communication using a microcontroller (such as an Arduino Uno) as the SPI master and the Analog Discovery Studio as the SPI slave. Using LabVIEW, students will be able to visualize the slave select, clock, and MOSI lines of the SPI bus and learn how to extract the message from these lines. Advanced students can challenge themselves by modifying their code to encode and decode ASCII signals or adding a layer of encryption to protect their data from unwanted observers.


Introduction

Serial Peripheral Interface Bus (SPI) interface is a high-speed method of communication between multiple devices over a short distance. A master slave configuration is used where the master provides the clock to the slave/s and determines the data rate for the communication.

Learning Objectives

In this section, students will:

  • Investigate the functionality of the different SPI lines
  • Learn how to transmit SPI from a master device
  • Validate the data sent from the master to check the data integrity

Part List

The following equipment is required for this experiment:

Hardware


SPI Master and Slave Configurations

As shown in the image to the right, the communication method generally uses four digital lines. The slave select on the master is connected to the slave select on the slave and the master informs the slave of when communication starts and stops. Unlike the UART protocol you learned in the previous lab, SPI is a synchronous protocol and the master and slave are synchronized using the same Clock line.

The two other digital lines are the Master Out, Slave In (MOSI) and the Master In, Slave Out (MISO). The MOSI is used to send data from the master to the slave. The MISO is used to send data back from the slave to the master.

For SPI communication, when the slave select is set to low, the master outputs a clock signal as seen in the diagram to the right. The slave then reads the current MOSI state on each rising edge of the clock.

In this lab, we will be using the Arduino Uno as the master, and we are now going to set up the Analog Discovery Studio as the slave. Triggering will be an important aspect of this section and therefore it is important to understand this concept before getting started.

As we will be reading the digital lines on the Analog Discovery Studio, we need a way of recognizing when the Arduino Uno is sending data. By using triggering, we can identify a rising or falling edge of a signal and from this, synchronize the reading of data at the correct time. You can think about it like someone knocking on your door where the knock is the trigger we are waiting for. The act of knocking is what we listen out for and triggers us to answer it. If people didn’t knock on your door when they arrived, you would continuously have to keep checking to see if someone is at the door. This would result in multiple unnecessary checks. This is the same for reading digital lines. If you don’t have a trigger, you must continuously read the lines as you don’t know when to expect the data. By using a trigger, we are telling the device when to expect data to start coming in.

Questions and Exercises
  • Identify the eight-bit Boolean value on the MOSI line (see the image above) and convert this value to hexadecimal (assume that the least significant bit is sent first).
  • If the sample rate of the digital signal on the master is 125 KS/s, what is the minimum sample rate of slave device in order to ensure lossless communication? Explain what will happen if the sample rate is set below this minimum value.
  • What characterizes a device as a master in a master-slave configuration when using SPI communication?
  • If you have a master-slave SPI communication setup and you don’t need to send data from the slave to the master, what are the names of the digital lines that you require? Explain your answer.
  • A trigger will be configured on the Slave Select line to signal the beginning of acquisition. Should we trigger on a rising or falling edge? What would happen if we triggered on the incorrect edge?
  • Explain how we can use the clock to synchronize reading data from the master (MOSI).
  • Why is the Slave Select required for SPI communication?

Analysis with LabVIEW

Now that we have learned about the different lines which make up SPI communication, we will now program the Arduino Uno in LabVIEW. Follow the steps below to setup the Arduino Uno for SPI communication as the master device. While these steps are written with the Arduino Uno in mind, you can use any LINX supported microcontroller as shown in the hardware requirements section.

One way to take those signals and recover the original message signal is to acquire the signal with the Logic Analyzer from the Analog Discovery Studio in LabVIEW. We will be doing this by sampling the signal using the Analog Discovery Studio and displaying it in LabVIEW. By taking advantage of LabVIEW’s ability to visualize data, we can see how each step in this process is accomplished.

This section of the lab will assume a working knowledge of the LabVIEW environment and basic programming conventions. For more information on getting started in LabVIEW, including the installation of the Digilent WaveForms VIs, please view the resources available here: Getting Started with LabVIEW and a Digilent Discovery Device.

Note: Before testing or running your LabVIEW code, make sure that WaveForms is not opened. The Digilent WaveForms VIs will throw an error if Digilent WaveForms is still open when you run your code.

Note: If you don't know what a VI does, you can check the Context Help by pressing Ctrl+H, then highlighting the respective VI.


Objectives

Design a VI in LabVIEW that will send an SPI signal on one of the microcontroller's pins using LINX and a VI that reads in a serial signal, displays the digital waveform and decodes it. You can build your own VIs, following the steps below, or you can download the VIs used in this guide from here: SPI.zip.

The first VI, SPI_send.vi, is used to send out data. The Front Panel of this VI contains control elements for setting the COM port to which the microcontroller is connected, setting the digital pins used to send data, setting the signal parameters (clock frequency, endian-ness, SPI mode, CS logic), entering the data to be sent and two buttons to send the data and to stop the program.

The Block Diagram contains, except from the control and indicator elements, the blocks needed for communication with the microcontroller and data processing.

The SPI_receive VI's Front Panel contains controls for selecting the used Test and Measurement device, setting the digital IO channels used for receiving, the signal parameters and an indicator to display the decoded data. The main element of this front panel is the Digital Waveform Graph used to display the received signal. A stop button is also present, allowing the user to stop the reception when they want.

The Block Diagram of this VI contains the blocks needed to control the Mixed Signal Oscilloscope and to decode the signal.

General Operation

The transmitter VI should configure the SPI bus as required, then output the data on the SPI bus of the connected microcontroller.

The receiver VI should set the Mixed Signal Oscilloscope in the desired mode, then wait for a signal. If the signal is received, it should display it. If no signal is received, the scope should be auto triggered, to prevent it blocking the program. After the channel was triggered, measurements should be restarted.

To decode the SPI signal, a subVI should be used, which gets the CPOL (clock polarity) and CPHA (clock phase) variables (these are set by the SPI mode), then finds the rising or falling edges of the SCK signal and reads the MOSI bits at these edges.

The image below presents the general program flow of these VIs.


Building and Configuring Your Circuit

Connect the ground of the microcontroller to the ground of the Analog Discovery Studio (black wire) and connect the SPI bus of the microcontroller to digital pins of the Analog Discovery Studio as follows:

Arduino Pin ADS Pin
SCK (13) DIO 2
MOSI (11) DIO 1
CS (10) DIO 0
GND GND

In this lab, the MISO pin of the Arduino UNO will not be connected to any DIO lines, as the slave device won't send data to the master. Also, connect the microcontroller to the PC with a USB cable.

You can download the wiring diagram here: wiring_diagram_spi.zip

Follow the instructions below to set up your microcontroller in LabVIEW and send out the SPI signal for this experiment. In LabVIEW navigate to Tools → MakerHub → LINX → LINX Firmware Wizard. Set the Device Family to the brand of microcontroller you are using, the Device Type to the microcontroller type, and the Firmware Upload Method to Serial / USB.

In the next window, select the COM port connected to your microcontroller, then hit Next. Click Next again and click Finish. This allows the LINX Toolkit to automatically configure the firmware to work with LabVIEW.

Note: The COM port can be identified by going to Windows Device Manager → USB Serial Port.

Important

In the latest version of LabVIEW, Digilent LINX VIs can be found in the Hobbyist panel. Tools like the Firmware Wizard are also placed in the Hobbyist submenu.


Software Setup

For this laboratory, we need two VIs: the transmitter and the receiver.

The Transmitter (SPI_send.vi)

As a first step, the control and indicator elements should be placed by right-clicking on the Front Panel and selecting the required element. Add a Send and a Stop button from the Boolean palette and a Numeric control to enter data. All the other control elements can be added by right-clicking on the respective inputs of the subvis from the LINX tab.

Arrange everything on the Front Panel. Rename the placed elements by double-clicking on their name.

In the Block Diagram, initialize the microcontroller connected to a serial port with the Open.vi from the LINX tab, then open and configure the SPI bus. Don't forget to add the necessary control element to the Front Panel.

In a while loop add an event structure and configure the triggering event to Mouse Up on the Send button. VIs in this structure will only be accessed when the send button is pressed. In the structure send the data using the respective VI from the LINX tab.

Add one more event to the structure, configured to be triggered by the Stop button. This event should stop the while loop.

When the program is finished, don't forget to close the MCU and handle the errors.

The Receiver (SPI_receive.vi)

Setup and Instrument Configuration

As a first step, the control and indicator elements should be placed by right-clicking on the Front Panel and selecting the required element. In this VI we need two Combo Boxes and two String indicators to set the Test and Measurement device and the DIO lines used. You can copy the Combo Boxes from the VI created in Lab 6: UART Serial Communications.

We need four control elements for setting the SPI signal parameters: a Numeric control for the clock frequency and three Rings or Enumerations for setting the CS logic level, the bit order, and the SPI mode.

Place a Digital Waveform Graph on the Front Panel, then turn off the auto-scaling for both axes. Right-click on the graph, click on Properties then select Cursors. Add 8 vertical cursors and set a visible style for them. Double click on the Front Panel anywhere to create a note. Create labels for the CS, MOSI, and SCK lines, then arrange these labels above the graph.

Create a numeric indicator to display the decoded data and a Stop button to interrupt the program if needed.

Arrange everything on the Front Panel. Rename the placed elements by double-clicking on their name.

In the Block Diagram create property nodes for the digital graph's YScale.Minimum, YScale.Maximum, XScale.Minimum and XScale.Maximum properties. Set the Y-axis range according to the selected digital channels (DIO 0 is on position 15, DIO 1 is on position 14, etc.). By default, the graph displays the whole buffer and the buffer size is 1000, so we can set the X-axis range from 0 to $1000t_{sample}$, where $t_{sample}=\frac{1}{f_{clock}\frac{1000}{2*nr_{bit}}}$, $f_{clock}$ being the clock frequency and $nr_{bit}$ the number of data bits (8).

Display the DIO lines used as MOSI and SCK with the respective indicators.

Open the Mixed Signal Oscilloscope (MSO), and configure it to acquire digital signals from the lines set as CS, MOSI, and SCK, with the sampling frequency of $f_{sample}=\frac{1}{t_{sample}}$. Enable the used digital channels, then set the Scope to be triggered by the rising/falling edge of the CS signal. Start the instrument.

Reception and Decoding

In a while loop, read the Scope. Compare the results to the ones from the previous iteration (to a blank array in the first iteration). If the results are the same as the previous ones, or the instrument was auto-triggered, restart it. If the instrument was triggered normally, convert the waveform to a boolean matrix, then extract the columns which contain MOSI and SCK data.

The SPI mode determines, when should we read the incoming data. There are four modes, with the corresponding CPOL and CPHA values:

SPI Mode CPOL CPHA
Mode 0 0 0
Mode 1 0 1
Mode 2 1 0
Mode 3 1 1

To decode the signal, find the indexes of all the rising/falling edges of the SCK signal, then save in an array the MOSI values at these indexes. To get the transmitted number, convert the binary array to a number.

You can use the indexes of the SCK signal edges and the ActCrs and Cursor.PosX property nodes of the digital waveform graph to set vertical cursors at these points, showing the moments when data is read.

If an error appears, or the Stop button is pressed, exit the loop and close the used instrument, disconnect the device, then handle the errors.

Questions and Exercises
  • Knowing that data is being sent from the master to the slave only and that Line 0 represents the CS, identify what line 1 and line 2 represent. Explain your reasoning.
  • Draw the waveform for Line 1 to represent the hexadecimal value “C9”.

Further Exploration

The topics below go over two ways you can continue exploring after finishing this lab.

Hello, World!

In this lab we explored how to transmit over SPI using hexadecimal values. However, this doesn’t allow us to send characters or symbols like “&” and punctuation marks. In order to send characters and symbols, we would need a code or look-up table to help convert binary numbers to actual characters. One of the earliest encoding schemes is called the American Standard Code for Information Interchange, or ASCII for short. The ASCII code established a table where different numerical values would represent different characters and symbols such as “a” and “tab”. Modify the data being sent to encode characters to hexadecimal numbers and then modify the data being received to decode hexadecimal numbers to ASCII characters.

Encryption

Once you have worked out how to send and receive ASCII characters, the next challenge is to encrypt your data so that your data cannot be read unknowingly. Explore the different types of encryption used in industry and see if you can come up with your own way of encrypting your data.


Next Steps

For more complementary laboratories, return to the Complementary Labs for Electrical Engineering page of this wiki.

For technical support, please visit the Test and Measurement section of the Digilent Forums.