Serial Peripheral Interface (SPI) Bus: A Deep Dive
Introduction to the SPI Bus
The Serial Peripheral Interface (SPI) bus is a synchronous, full-duplex communication standard primarily used for data transfer between integrated circuits in electronic equipment. It utilizes a clock line, incoming and outgoing data lines, and a chip select pin to control device communication.
SPI Bus Management in C
Four C functions are associated with the SPI module when the microcontroller hardware selects SSP. These functions provide a software implementation of the SPI module:
1. setup_spi()
void setup_spi(const mode);
This function initializes and configures the SPI, defining its operating mode. Several tags within the microcontroller’s header file (.h) define these modes, categorized into three groups:
a) Mode
SPI_MASTER
: Sets the device as master.SPI_SLAVE
: Configures the device as slave.SPI_SS_DISABLED
: Disables the slave select (SS) pin.
b) Flank
Configures SPI transmission modes based on these combinations:
SPI_L_TO_H
: Low to high flank (rising edge).SPI_H_TO_L
: High to low flank (falling edge).
Mode Configuration Table
Motorola | Microchip | CCS |
---|---|---|
SPI Mode 0,0 | CKP = 0, CKE = 1 | SPI_L_TO_H |
SPI Mode 0,1 | CKP = 0, CKE = 0 | SPI_L_TO_H | SPI_XMIT_L_TO_H |
SPI Mode 1,0 | CKP = 1, CKE = 1 | SPI_H_TO_L |
SPI Mode 1,1 | CKP = 1, CKE = 0 | SPI_H_TO_L | SPI_XMIT_L_TO_H |
CKP = Clock Polarity Select bit
CKE = Clock Edge Select bit
c) Frequency
Defines the clock frequency. Used only when the device is configured as master (the clock signal generator).
SPI_CLK_DIV_4
SPI_CLK_DIV_16
SPI_CLK_DIV_64
SPI_CLK_T2
Combine flags using the OR operator (|). Examples:
- Master device, Mode B (0,1), specific clock speed:
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
- Slave device, Mode C (1,0), SS pin disabled:
setup_spi(SPI_SLAVE | SPI_H_TO_L | SPI_SS_DISABLED);
2. spi_write()
void spi_write(char c);
Writes the next character to the SPI port. Master devices generate a clock signal and send the value immediately. Slave devices send the value upon receiving a clock signal from the master.
3. spi_read()
char spi_read([char c]);
This function’s behavior depends on the device’s role (master or slave). It returns data read through the SPI and may accept a parameter.
Master: Sends the value c
while receiving a new value (d = spi_read(c)
). If no data needs sending but a read operation is required, pass zero (d = spi_read(0)
). If spi_write()
was used previously and you want to read data while writing, use this function without parameters (d = spi_read()
).
Slave: Waits for the master to send the clock signal and data. While receiving new data, it sends data c
to the other device. Use spi_data_is_in()
to check for received data.
4. spi_data_is_in()
char spi_data_is_in();
Returns TRUE
if data has been received via the SPI port.
Example Code
This example demonstrates communication between a master and a slave. To compile for the master, uncomment #define MASTER_DEVICE
.
#include <16f877.h>
#fuses HS, NOWDT // For a Microchip PIC16F877
#use delay(clock=10000000)
#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8)
#use standard_io(D)
//#define MASTER_DEVICE
#ifdef MASTER_DEVICE
// (Master)
void main() {
int8 c, d;
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
printf("Press any key to begin");
while (1) {
c = getchar();
output_D(0xFF ^ c); // Toggle LEDs corresponding to PORTD
// Method 1: Separate write and read
spi_write(c);
d = spi_read();
// Method 2: Combined write and read
//d = spi_read(c);
putchar(c);
}
}
#else
// (Slave)
void main() {
int8 c;
setup_spi(SPI_SLAVE | SPI_L_TO_H | SPI_CLK_DIV_16);
while (1) {
// Flash C2 to indicate activity
output_low(PIN_C2);
delay_ms(100);
output_high(PIN_C2);
delay_ms(100);
// Method 1: Check for data before reading
if (spi_data_is_in()) {
c = spi_read();
output_D(0xFF ^ c); // Toggle LEDs on PORTD
spi_write(c); // Wait for master signal and write data
}
// Alternative method: Combined read and write
//c = spi_read(c);
//output_D(0xFF ^ c);
}
}
#endif
More complex libraries offer additional specialized functions for SPI bus management.