First, What Is It
- SPI (Serial Peripheral Interface): a high-speed, full-duplex, master-slave serial bus — often used for Flash, displays, and sensors that need speed.
- Master-slave: exactly one master (provides the clock and initiates transfers); the rest are slaves that respond passively.
- Four wires: a dedicated clock line, two data lines (one per direction), and a chip-select line — which is why SPI is fast and its timing is simple.
Breaking Down the Principle
1. What Each Wire Does
| Signal | Full name | Direction (master view) | Role |
|---|---|---|---|
| SCLK | Serial clock | master → slave | One pulse transfers one bit, synchronizes both sides |
| MOSI | Master out, slave in | master → slave | Master sends data |
| MISO | Master in, slave out | slave → master | Slave returns data |
| CS/SS | Chip select | master → slave | Pulled low to select a slave |
One clock line + two data lines = full duplex: every clock cycle sends one bit and receives one bit simultaneously.
2. Chip Select: Choosing "That One" Slave
Many slaves can share the bus, but only one is active at a time: the master pulls the target slave's CS low; all other slaves keep CS high and stay silent. So which IO the CS is wired to must match the code configuration.
3. Clock Polarity (CPOL) and Phase (CPHA): The Pair Everyone Mixes Up
SPI does not specify on which clock edge data is sampled — both ends must agree:
- CPOL (polarity): whether the clock idles low or high (0 = idle low, 1 = idle high).
- CPHA (phase): whether data is sampled on the first or second edge (0 = first edge, 1 = second edge).
They combine into 4 modes (SPI Mode 0~3):
| Mode | CPOL | CPHA | Note |
|---|---|---|---|
| Mode 0 | 0 | 0 | Most common, default for many devices |
| Mode 1 | 0 | 1 | Rare |
| Mode 2 | 1 | 0 | Rare |
| Mode 3 | 1 | 1 | Samples on first edge like Mode 0 but idle level is high |
If the datasheet says "SPI Mode 0" and the code uses Mode 3, data will be shifted or completely wrong. This is one of the most common SPI debugging traps.
4. Speed and Data Width
- Transfer speed is set by the SCLK frequency, configured by the master; slaves have a maximum rate (e.g., Flash commonly 50~100 MHz) — exceeding it causes errors.
- Data width is commonly 8 bits, with 16/32-bit modes on some parts; match the device datasheet.
How the SDK Implements It
- Related pages: SPI Protocol, Flash Internal Storage
The SDK pattern for SPI is "define device struct → configure mode/rate → read/write" (the WB2 SDK uses the HOSAL unified peripheral layer, and the configuration is written into the config fields of the hosal_spi_dev_t struct):
hosal_spi_dev_t spi; /* Define the device struct directly — no get_by_name */
/* Master mode, Mode 0 (CPOL=0, CPHA=0), 8-bit data (fields per the SDK's hosal_spi.h) */
spi.config.mode = HOSAL_SPI_MODE_MASTER;
spi.config.freq = 1000000; /* SCLK 1 MHz */
hosal_spi_init(&spi);
hosal_spi_send(&spi, tx_buf, len, 0); /* MOSI out */
hosal_spi_send_recv(&spi, tx_buf, rx_buf, len, 0); /* Full-duplex: MISO in */Reading a Flash/sensor ("send command first, then read data") is essentially repeated SPI transfers with CS held low throughout.
Common Exam & Interview Questions
Why is SPI faster than UART?
SPI has a dedicated clock line (SCLK) for synchronization and can run at very high frequencies; UART samples asynchronously by baud rate, limited by both ends' accuracy and clock drift.
What is the difference between SPI Mode 0 and Mode 3?
Both sample on the first edge; the difference is the idle clock level — Mode 0 idles low, Mode 3 idles high. A mismatch with the datasheet causes wrong sampling.
How are multiple slaves distinguished on one SPI bus?
By chip select: only one slave's CS is pulled low at a time; the others keep CS high and stay silent. Each slave has its own CS pin.
What happens if MOSI and MISO are swapped?
The master and slave then send to each other's send line — both fail to receive (all 0s/1s or garbage). This is a wiring-level classic.
Why is SPI full-duplex while I2C is half-duplex?
SPI has independent MOSI/MISO data lines, so it can send and receive simultaneously; I2C has a single SDA data line, so only one direction at a time.
Have questions?
For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

