This one is about the wire, not the chip. Nothing below changes with the board you picked, which is why the chip and language switches are not on it. They come back on the ESP32 pages this one sits underneath.
SPI and chip select
SPI shares three wires between every device and gives each one a private pin to say "I mean you". That buys it about a hundred times the speed of I2C and costs it a pin per device — the whole trade, in one sentence.
Add devices, then pull two chip selects low at once. Nothing on the bus objects, which is the point.
Three shared wires and one private one
- SCK — the clock, always driven by the master.
- MOSI — master out, slave in.
- MISO — master in, slave out.
- CS (or SS, or NSS) — one per device, active low.
While a device's CS is high it holds MISO in high impedance: electrically not connected. Pull one CS low and that device joins the bus. That is the entire addressing scheme, and it lives in copper rather than in the protocol.
Nothing here checks anything
SPI has no addresses, no acknowledgement, no error detection and no defined speed. The master clocks bits out; a bit comes back on every clock whether or not anybody is there. Read a disconnected SPI device and you get 0xFF or 0x00 — a perfectly valid byte from nothing at all.
Two chip selects low is two outputs fighting. One device pushes MISO high while another pulls it low. There is no arbitration to save you the way there is on I2C, because MISO is push-pull, not open-drain. The master reads whichever wins and both parts get hot. Exactly one CS may be low at a time.
A floating CS is the same bug wearing a disguise. A pin that has not been set
to OUTPUT and driven high is at the mercy of the room, and a device that decides
it is selected will join in the middle of someone else's transfer. Drive every
CS high in setup(), before anything else touches the bus.
Duplex, and why displays like it
Every clock tick sends a bit and receives a bit at the same time. There is no turnaround, no ACK, no per-byte overhead: a byte is eight clocks, full stop. At 40 MHz that is 5 MB/s, against roughly 40 kB/s for I2C at 400 kHz.
That is why an SPI screen redraws instantly and the same panel over I2C wipes visibly down the display, and why SD cards and flash chips are SPI without exception.
Modes, which is the one setting people get wrong
Two bits describe when data is valid: clock polarity (idle high or low) and clock phase (sample on the first edge or the second). Four combinations, called mode 0 to mode 3. Almost everything is mode 0; a few displays are mode 3.
Wrong mode does not error. It returns bytes, shifted by one bit, which is why "garbage but structured" is the symptom.
#include <SPI.h>
#define CS_DISPLAY 5
#define CS_SD 15
void setup() {
pinMode(CS_DISPLAY, OUTPUT); digitalWrite(CS_DISPLAY, HIGH);
pinMode(CS_SD, OUTPUT); digitalWrite(CS_SD, HIGH);
SPI.begin();
}
uint8_t readReg(uint8_t cs, uint8_t reg) {
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
digitalWrite(cs, LOW);
SPI.transfer(reg | 0x80); // top bit: read, on most parts
uint8_t v = SPI.transfer(0x00); // clock out a dummy byte to clock one in
digitalWrite(cs, HIGH);
SPI.endTransaction();
return v;
}beginTransaction matters as soon as two devices want different speeds or
modes — it applies that device's settings and locks the bus for the duration.
Choosing between the two
Registers, settings, a sensor read a few times a second: I2C, two pins, done. Anything with a frame buffer or a filesystem behind it: SPI, and pay the pins.
Running out of chip selects is a real constraint on small boards, and the answers are the ordinary ones — a shift register to make more outputs, or an I2C expander to make them somewhere else.
The same three wires with the ESP32's HSPI and VSPI behind them, and what to do when you run out of chip selects.
SPI →Edit this page — content/esp32/spi-and-chip-select.mdx
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.