Wednesday, August 31, 2011

Microchip SPI Basics Tutorial For PIC18

             The Serial Peripheral Interface (SPI) is one of the popular embedded serial communications widely supported by many of today’s chip manufacture and it considered as one of the fastest serial data transfer interface for the embedded system. Because of its special in/out register configuration, the SPI master device could transfer its data and at the same time it receive a data from the SPI slave device with the clock speed as high as 10 MHz. Beside its superior data transfer speed; SPI also use a very simple data transfer protocol compared to the other serial data transfer methods. When the SPI master device want to send the data to the SPI slave device then the SPI master will just simply shifting its own data through a special 8-bits register and at the same time the SPI master will receive the data from the SPI slave into the same register as shown on this following picture.

           With this circular shift register connection between the SPI master and the SPI slave devices, the complete data transfer from both devices will be accomplished in just 8 clock cycles. This means the SPI devices only need about 0.8 us to complete transfer the 8-bit data if we use 10 MHz clock. One of the drawbacks using the SPI especially when we use multiple SPI slave device is the SPI slave could not initiate sending its own data to the SPI master device, all the data transfer initiation is always come from the SPI master. The SPI master device has to poll each of the SPI slave devices to know whether the SPI slave device has a data to be sent to the SPI master device or not.

           Polling the entire SPI slave devices will eventually consumed the SPI master resources when the SPI slave devices to be polled increase, therefore some of the SPI slave device is equipped with the interrupt pin to notify the SPI master device that it has a data to be read.

The PIC18F458 Microcontroller

On this tutorial I will use the Microchip PIC18F458 microcontroller, this microcontroller is one of my favorite 8-bit 40-pins PIC18 microcontroller families members as it is equipped with sophisticated advanced peripheral inside such as ADC, USART, ECCP (Enhanced Capture/Compare/PWM), SPI, I2C . With 32K bytes flash ram and equipped with the build in circuit debug, this 8-bit 20-pins microcontroller is a perfect choice for serious embedded application or just for hobbyist’s project.

The PIC18F458 microcontroller SPI peripheral support both master and slave mode but on this tutorial we will only exposing the PIC18F458 SPI master mode.we will be using 74LS395 shift register ic To expand  the serial bit into parallel configuration.

As 74LS395 is only 4 bit shift register so we will be able to see only four Least Significant bits. you can use 74LS595 to display all 8 bits if you want to, but for now we will be working with 74LS395 4 bit shift register.

74LS395 Pin Configuration And Function Table  

Hardware Connection
Programming The PIC:-


#pragma config OSC = HS, OSCS = OFF
#pragma config PWRT= OFF , BOR=ON, BORV = 45
#pragma config WDT = OFF

#include <p18f458.h>

void spi(unsigned char);             //SPI Function To send the data

void delayMs(int x);                     // to generate some delay

void main()                                  // main program starts here
SSPSTAT =0x40;              // Configure SSPSTAT  for transmission occur from idle to active clock and Buffer flag =0

SSPCON1=0x22;              //Configure  SSPCON1 for ENABLE SERIAL PORT
                                                    // and disable general I/O pin ,, SPI master clock= Fosc/64

  TRISC=0;                          //Configure PORT C as output ,,
                                                    // we are only sending the data so we do't need to set SPI pin as input

while(1)                      // loop for ever so that led keep repeating that pattern
spi(0x01);                   // send 01 hex to the SPI port it will glow the first led

delayMs(1000);          // wait for approximate 1sec   ,
                                                     //if we do't give the delay then led will flash too fast that
                                                    // we can't even know when it glow and when it off

spi(0x02);                   //send 02 hex to the SPI port it will glow the send led   ,
                                                     //if you want to glow both led same time send 03 hex and so  on

delayMs(1000);           // wait for 1 sec


void spi(unsigned char myData)
SSPBUF = myData;                    // put the data in the SSPBUF register which going to be send

while(!SSPSTATbits.BF);           // wait until the all bits sended

void delayMs(int x)              // a general delay function
int i;
for (x ;x>0;x--)
for (i=0;i<=110;i++);

DOWNLOAD MPLAB PROJECT , Source Code and Firmware 

How to Decide SSPSTAT and SSPCON1  register value 


  1. how u make to drive 9 leds,74ls395 have only 4bit output?

  2. hi
    i m just driving only 4 led other 5 led are disconnected (no use)

    but if you want to drive more led with only 4 output pins then use multiplexing

    or use can also use 74ls595 with 8 output lines

  3. Hi Dear

    Thanks for you kind information. I have varified its and it is 100% Working. It would be kind of u if u add spi read section as well.

  4. hi
    what about in master slave mode and with transmit receive both enabled?

  5. HI, can i know how do you use spi to communicate with another board? as I done the code, but my voltage isnt measuring is it possible to help me check my code?

  6. hi
    could you please send the Proteus file as i tested the code in mikroC but the clock did not initialized and nothing is working!!!

    Thank you

  7. Hello

    I am unable to understand
    SSPSTAT =0x40; // Configure SSPSTAT for transmission occur from idle to active clock and Buffer flag =0
    datasheet says if it,s bit CKE = 1 means active to idle, but you says idle to active. What am i not undurstanding.
    Please explain