Watch the Video Tutorial

SPI stands for Serial Peripheral Interface. The SPI protocol was initially developed and proposed by Motorola for use in microprocessor and microcontroller based interface applications. 
In a system that uses the SPI bus, one device acts as the master and other devices act as slaves. The master initiates a communication and also provides clock pulses to the slave devices. 
SPI is implemented in the PIC microcontrollers by a hardware module called the Synchronous Serial Port or the Master Synchronous Serial Port (MSSP). This module is built into many different PIC microcontroller devices. It allows serial communication between two or more devices at a high speed and is reasonably easy to implement The MSSP can operate either in I²C or SPI mode.
SPI is usually called a 4-wire full duplex synchronous serial communication, the functions of the 4 wires are as follow:
SCLK (Serial Clock): This is the serial clock signal. It is generated by the master device and controls when data is sent and when it is read. The SCLK pin of master is connected to SCLK pin of slave.
MOSI (Master Out Slave In) or SDO (Serial Data Output) This pin carries data out of a device (from master to slave).
MISO (Master In slave Out) or SDI (Serial Data In) This pin carries data into a device (from slave to master).
SS (Slave Select) or CS (Chip Select): This pin allows a master device to indicates to a slave that the master  wishes to start an SPI data exchange between that slave device and itself. The signal is most often active low, so a low on this line will indicate the SPI is active and communication can take place, while a high will signal inactivity.
This signal must be used when more than one slave exists in a system, but can be optional when only one slave exists in the circuit but it always a good practice to use it. Depending on the number of devices in the bus, we can have more than one chip Select lines, one per device in the bus. Figure 1 hows the microcontroller connected to 3 SPI slaves (3 chip select lines).
SPI is used for connecting peripherals to each other and to microcontrollers.
There are many devices that support the SPI protocol and can easily communicate with a microcontroller via SPI: A/D converters, D/A converters, SD Cards, Liquide Crystal Displays (LCD), Real Time Clocks like the DS1306, serial display drivers like MAX7219 , Serial EEPROM like 25LC256 , etc.  
Depending on the number of slave devices connected, the master will have one dedicated pin for SS line for each slave. Figure 1 below shows an illustration of one master (microcontroller) controlling three slave devices.

SPI Bus

 Figure 1: SPI Bus

Advantages of SPI:

  • Full duplex communication.
  • It’s faster than asynchronous serial and I2C allowing large quantities of data to be transferred quickly. SPI can operate at extremely high speeds but generally dictated by the slowest device on the bus. Common bus speeds are in the 1-100Mbits per second range
  • The hardware protocol is simple to implement, the receiver hardware can be a simple shift register. Transceivers are not needed, slaves use the master’s clock and don’t need precision oscillators
  • It supports multiple slaves
  • Complete protocol flexibility for the bits transferred, this is not limited to 8-bit words and arbitrary choice of message size, content, and purpose
  • Lower power requirements than I²C due to less circuitry and no need for pull-ups resistors

Disadvantages of SPI:

  • It requires more signal lines due to the fact that each slave must have its own CS line, this will require more wires than other serial communications especially when many slaves are involved.
  • The master must control all communications (slaves can’t talk directly to each other)
  • SPI is designed for fairly short range i.e. on the same PCB as the Master or via a relatively short cable compared to RS-232, RS-485, or CAN-bus

MikroC Pro for PIC SPI Bus Library Functions 

Programming an SPI Bus communication is not difficult, most of the compilers provide librarie routines which make it easy. The mikroC PRO for PIC provides SPI library for easy communication of a microcontroller in SPI Master mode with devices. 
Below is a quick descriptions of SPI routines and functions For more information, please visit online the mikroC pro for PIC SPI library page.

Notes:

  • Not all PIC Microcontrollers have an SPI module. For those which don’t have an SPI module or if any input/output either than the default hardware pins are required, the Software SPI functions can be used.
  • SPI routines require you to specify the module you want to use because some microcontrollers have more than 1 SPI modules. To select the desired SPI, simply change the letter x in the prototype for a number from 1 to 2. Number of SPI modules per microcontroller differs from chip to chip that is why it is always good to read the appropriate datasheet before using this library.
  • For those microcontrollers which have multiple SPI modules, Switching between the SPI modules in the SPI library is done by the SPI_Set_Active function (SPI module has to be previously initialized).
  • Some microcontrollers do not support SPIx_Init_Advanced routine. Please, refer to the appropriate datasheet.
  • Certain SPI lines on some PIC16 Enhanced Family MCUs can be routed through a alternative pins.

These pins are selected by configuring APFCON register and appropriate TRIS register

SPIx_init

This routine configures and enables SPI module with the following settings:

  • Master mode
  • Clock Fosc/4
  • Clock idle state low
  • Data transmitted on low to high edge
  • Input data sampled at the middle of interval

Prototype: void SPIx_Init();

The microcntroller has to have a hardware integrated SPI module before you can use this function.

Example

SPIx_Init_Advanced 

This routine configures and enables SPI module with advanced settings that you can specify manually. This routine or the SPIx_Init routine must to be called before using other functions of SPI Library.

Prototype: void SPIx_Init_Advanced(unsigned short master_slav, unsigned short data_sample, unsigned short clock_idle, unsigned short transmit_edge);

Parameters: mode, data_sample and clock_idle configure the SPI module, and can have the following values:

Description Predefined library const
SPI mode:
Master clock = Fosc/4 _SPI_MASTER_OSC_DIV4
Master clock = Fosc/16 _SPI_MASTER_OSC_DIV16
Master clock = Fosc/64 _SPI_MASTER_OSC_DIV64
Master clock source TMR2 _SPI_MASTER_TMR2
Slave select enabled _SPI_SLAVE_SS_ENABLE
Slave select disabled _SPI_SLAVE_SS_DIS
Data sampling interval:
Input data sampled in middle of interval _SPI_DATA_SAMPLE_MIDDLE
Input data sampled at the end of interval _SPI_DATA_SAMPLE_END
SPI clock idle state:
Clock idle HIGH _SPI_CLK_IDLE_HIGH
Clock idle LOW _SPI_CLK_IDLE_LOW
Transmit edge:
Data transmit on low to high edge _SPI_LOW_2_HIGH
Data transmit on high to low edge _SPI_HIGH_2_LOW

The microcontroller has to have a hardware integrated SPI module before you can use this function.

Example

SPIx_Read

This function reads one byte from the SPI bus and returns the received data.

Prototype: unsigned short SPIx_Read(unsigned short buffer);

Parameters: buffer: dummy data for clock generation

Before you can use this function, the SPI must be initialized and communication established See SPIx_Init_Advanced or SPIx_Init.

Example:

SPIx_Write

This function writes byte via the SPI bus.

Prototype: Parameters: wrdata: data to be sent

Before you can use this function, the SPI must be initialized and communication established See SPIx_Init_Advanced or SPIx_Init.

Example:  

SPI_Set_Active

This function sets the active SPI module which will be used by the SPI routines and it is only available with microcontroller with two SPI modules. After using this function, they will be no need anymore to specify the SPI module to use during read or write operations.

Prototype: void SPI_Set_Active(char (*read_ptr)(char), void(*write_ptr)(char))

Parameters: read_ptr: SPIx_Read handler

write_ptr: SPIx_Write handler

Before you can use this function, the SPI must be initialized and communication established See SPIx_Init_Advanced or SPIx_Init.

Example:

SPI_Read 

This function is the same as SPIx_Read it uses the active SPI module previously activated by the SPI_Set_Active routine.

SPI_Write

This function is the same as SPIx_Write it uses the active SPI module previously activated by the SPI_Set_Active routine.

In the Interfacing SD Card with PIC Microcontroller article, an example of how to read and write data to or from an SD Card with mikroC Pro for PIC Compiler is explained.