I. SPI basic principles


1. What is SPI?

SPI (Serial Peripheral Interface) is a synchronous serial communication protocol, commonly used for high-speed data transmission between microcontrollers and peripherals (such as sensors, memory, display screens).

Features:

Full-duplex communication (simultaneous transmission and reception).

Master-slave architecture (one master device controls multiple slave devices).

Four-wire system: SCK (clock), MOSI (master output slave input), MISO (master input slave output), SS (slave device selection).

2. SPI mode

SPI has 4 operating modes, determined by clock polarity (CPOL) and clock phase (CPHA):

model

CPOL

CPHA

Clock idle state

Data sampling timing

Mode 0

 0

0

Low level

SCK first edge (rising edge)

Mode 1

0

1

Low level

SCK second edge (falling edge)

Mode 2

1

0

High level

SCK first edge (falling edge)

Mode 3

1

1

High level

SCK second edge (rising edge)

Key points: CPOL: The level when the clock is idle (0 = low level, 1 = high level).
CPHA: The edge of data sampling (0 = first edge, 1 = second edge).

Ⅱ. SPI configuration steps

1. Hardware connection

Master device pins: SCK, MOSI, MISO, SS (usually controlled by the master device).
Slave device pins: SCK, MOSI, MISO, SS (need to be grounded or pulled down by the master device).
Notes:
SCK, MOSI, MISO of the master and slave devices must be directly connected (no pull-up/pull-down resistors).
SS pin needs to be manually controlled (software or hardware trigger).

2. Software configuration

Take STM32 and Arduino as examples:

(1) STM32 HAL library configuration

// Initialize SPI parameters

SPI_HandleTypeDef hspi1;

hspi1.Instance = SPI1;

hspi1.Init.Mode = SPI_MODE_MASTER;          // Main Mode

hspi1.Init.Direction = SPI_DIRECTION_2LINES;// Full Duplex

hspi1.Init.DataSize = SPI_DATASIZE_8BIT;    // 8-bit data

hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;  // CPOL=0

hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;      // CPHA=0(Mode 0)

hspi1.Init.NSS = SPI_NSS_SOFT;              // Software Control SS

hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; //Baud rate division

hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;     // MSB First

hspi1.Init.TIMode = SPI_TIMODE_DISABLE;     // Turn off TI mode

hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // Turn off CRC

// Initialize SPI

HAL_SPI_Init(&hspi1);

(2) Arduino configuration

#include <SPI.h>

void setup() {
  SPI.begin();                // Initialize SPI pins (SCK, MOSI, MISO, SS)
  pinMode(SS, OUTPUT);        // SS must be set as output (to avoid entering slave mode)
  digitalWrite(SS, HIGH);     // Initially disable the slave device
}

// Send data (SPI transfer function)
byte transferData(byte data) {
  digitalWrite(SS, LOW);      // Activate slave device
  byte received = SPI.transfer(data); // Sending and receiving data
  digitalWrite(SS, HIGH);     // Release slave device
  return received;
}

III. SPI communication process

The master pulls down SS: activates the slave.

The master generates a clock signal: synchronizes data transmission through SCK.

Data transmission:
The master sends data through MOSI, and the slave returns data through MISO.

Data is sampled at the specified edge of SCK (determined by CPHA).

The master pulls up SS: ends communication.

IV. Key configuration parameters

Baud rate (clock frequency):
The master sets the SCK frequency through a frequency divider (such as STM32's BaudRatePrescaler).

Make sure it does not exceed the maximum supported frequency of the slave.

Data order:

MSB (high bit first) or

LSB (low bit first).

Chip select signal (SS) management:

Hardware SS (dedicated pin) or software SS (general GPIO).

V. Common Problems and Solutions

1. Communication failure (data error)

Possible causes:
SPI mode mismatch (CPOL/CPHA setting error).
Pin connection error (such as MOSI/MISO reverse connection).
Clock frequency is too high (slave device cannot respond).
Solution:
Check the SPI mode requirements in the slave device data sheet.
Use a logic analyzer to check the SCK, MOSI, and MISO waveforms.

2. Unstable data transmission

Possible causes:
Long-distance wiring causes signal interference.
Lack of pull-up resistors (MISO/MOSI lines are floating).
Solution:
Shorten the wiring or use shielded wires.
Connect a 4.7kΩ pull-up resistor to the MOSI/MISO line.

3. The SS pin is automatically pulled low

Possible causes:
In hardware mode, the SS pin level change triggers the slave mode (such as the SS pin level sensitivity of AVR).
Solution:
Set to software SS of master device (such as pinMode(SS, OUTPUT) of Arduino).

VI. Debugging Tools

Logic Analyzer: Capture SPI waveforms and analyze clock and data timing.

Recommended tools: Saleae Logic, DSLogic.

Oscilloscope: Check SCK frequency and signal integrity.

VII. Application Scenario Examples

Sensor reading: such as temperature sensor (MAX31865), accelerometer (MPU6050).

Memory access: such as Flash (W25Q64), EEPROM (AT25DF041).

Display control: such as TFT LCD with SPI interface.

Summary


SPI configuration core: correctly set mode (CPOL/CPHA), baud rate, and data sequence.

Hardware Note: Ensure that the SS pin is managed correctly to avoid signal interference.

Debugging tips: Use a logic analyzer to verify timing and refer to the slave device data sheet.

Through reasonable configuration and debugging, SPI can achieve efficient and stable data transmission and is widely used in embedded systems.