What is SPI?
SPI is a protocol is simply a way to send data from device to device in a serial fashion (bit by bit). This protocol is used for things like SD memory cards, MP3 decoders, memory devices and other high speed applications.
We can compare SPI to other data transfer protocols:
|PINS||3 + 1 per device||2||2|
|Number Of Devices||unlimited||2||1024|
|Bits in one data byte transfer||8||10 (8 bytes + 1 start bit + 1 stop bit)||9 (8 bytes + 1 ack bit)|
|Must send one device address byte before transmission||No||No||Yes|
|Clock Type||Master clock only||Both device clocks must match||Master Clock that slave can influence|
|Data can transfer in two directions at the same time (full-duplex)||Yes||Yes||No|
As you can see SPI sends the least bit's per data byte transfer byte and does not need to send a device address before transmission. This makes SPI the fastest out of the three we compared.
Although SPI allows "unlimited" devices, and I2C allows for 1024 devices, the number of devices that can be connected to each of these protocol's are still limited by your hardware setup. This tutorial does not go into detail about connecting a large number of devices on the same bus. When connecting more devices, unrevealed problems may appear.
How does SPI work?
Firstly, SPI works in a master/slave setup. The master is the one that sends the clock pulses. At each pulse, data will be sent and received.
SPI has a chip select pin. Every device will share the "SDI", "SDO" and "Clock" pins, but each device will have it's own chip select pin (also known as slave select). This means we can have a virtually unlimited number of devices on the same SPI bus. You should also note that the chip select pin can be active high or active low depending on the device.
For some devices, the chip select pin must stay enabled throughout the transmission, and others require a change in the chip select line before the next transmission.
SPI is Dual-Duplex. This means data can be sent and received at the same time. If you wish to send data and not receive any, the PIC will receive data anyways. You may ignore the return byte.
Here's a diagram showing the way in which SPI sends & receives data:
If you are using a device that does not yet have a Jallib library, you will need to get the devices SPI mode. Some device datasheets tell you the SPI mode, and some don't. Your device should tell you the clock idle state and sample edge, with this information, you can find the SPI mode. SPI devices can be set to run in 4 different modes depending on the clock's idle state polarity & data sample rising or falling edge.
The image above is SPI mode 1,1. See if you can understand why.
Clock Polarity (CKP) - Determines if the clock is normally high or normally low during it's idle state.
If CKP = 1 - the clock line will be high during idle.
If CKP = 0 - the clock will be low during idle.
Data Clock Edge (CKE) - The edge that the data is sampled on (rising edge or falling edge)
If CKP = 0, CKE = 0 - Data is read on the clocks rising edge (idle to active clock state)
If CKP = 0, CKE = 1 - Data is read on the clocks falling edge (active to idle clock state)
If CKP =1, CKE = 0 - Data is read on the clocks falling edge (idle to active clock state)
If CKP = 1, CKE = 1 - Data is read on the clocks rising edge (active to idle clock state)
We can put this in a chart to name the modes:
Using The Jallib Library
At the moment, there is only a SPI master hardware library, therefore any device you wish to control must be connected to the PIC's SDI, SDO, SCK pins. The chip select pin can be any digital output pin.
The library requires you to set the pin directions of the SDI, SDO, SCK lines as follows:
-- setup SPI include spi_master_hw -- first include the library -- define SPI inputs/outputs pin_sdi_direction = input -- spi data input pin_sdo_direction = output -- spi data output pin_sck_direction = output -- spi data clock
You only need to set the pin direction of the chip select pin, the PIC will set the direction of the SDI, SDO & SCK for you. You will Alias this chip select pin as required by the device's jallib library.
If you are using more then one device in your circuit, you will need to declare your chip select pin near the beginning of your program. If you do not do this at the beginning of your program, some of your devices may receive data because their chip select pin could be enabled during init procedures of other devices on the SPI bus.
-- choose your SPI chip select pin -- pin_SS is the PIC's slave select (or chip select) pin. ALIAS device_chip_select_direction is pin_SS_direction ALIAS device_chip_select is pin_SS device_chip_select_direction = output -- chip select/slave select pin device_chip_select = low -- disable the device
Now the last step in setting up the SPI library is to use the init procedure.
Use the SPI mode name chart to get your SPI mode. The modes can be any of the following:
You will also need to set the spi bus speed. Here is a list of the speeds you may choose from:
SPI_RATE_FOSC_4 -- oscillator / 4
SPI_RATE_FOSC_16 -- oscillator / 16
SPI_RATE_FOSC_64 -- oscillator / 64
SPI_RATE_TMR -- PIC's internal timer
You will use the following init procedure with your custom values entered:
spi_init(SPI_MODE_11,SPI_RATE_FOSC_16) -- choose spi mode and speed
Now your ready to use the procedures to send and receive data. First you must enable the device with the chip select line:
device_chip_select = high -- enable the device
You can use the pseudo variable spi_master_hw to send and receive data as follows:
-- send decimal 50 to spi bus spi_master_hw = 50
Or receive data like this:
-- receive data from the spi port into byte x var byte x x = spi_master_hw
You can also send and receive data at the same time with the spi_master_hw_exchange procedure. here's an example:
-- send decimal byte 50 and receive data into byte x var byte x x = spi_master_hw_exchange (50)
When your done transmitting & receiving data, don't forget to disable your device
device_chip_select = low -- enable the device
The Jallib spi_master_hw library - Written by William Welch
Microchip Technology SPI Overview - http://ww1.microchip.com/downloads/en/devicedoc/spi.pdf