The SPI bus is a high-speed synchronous serial protocol. In exchange for using more wires, it gives us cleaner signals and fairly straightforward logic.
We’ve seen that I2C is great because it uses few wires, but it has a flaw: it’s “slow” and electrically complex (pull-up resistors, addresses…).
When engineers designed SPI (Serial Peripheral Interface), they decided to sacrifice the number of wires in exchange for one thing: Speed.
The usual fast mode for I2C reaches 400 kbit/s, while many SPI devices operate at several megahertz. The maximum frequency depends on the controller, the peripheral, the wiring, and signal integrity.
The 4 Horsemen of SPI
Unlike I2C’s two wires, here we use four. It’s worth knowing what each one does to avoid crossing them.
SCK (Serial Clock): The Clock
Just like in I2C, this is a Synchronous protocol. The Master generates the clock pulses.
- The difference is the speed. Here, the clock flies.
- Each pulse marks the sending and receiving of one bit.
MOSI (Master Out Slave In)
This is the data line going from the Master to the Slave. (Note: In modern standards, to avoid master/slave terminology, this is increasingly called COPI - Controller Out Peripheral In).
MISO (Master In Slave Out)
This is the data line going from the Slave to the Master. (Modern note: CIPO - Controller In Peripheral Out).
CS or SS (Chip Select / Slave Select)
Here, there are no “hexadecimal addresses” like in I2C. To talk to a specific chip, the Master has a direct wire connected to that chip’s CS pin.
- The logic is usually Inverse (Active Low).
- If you set the CS pin to LOW, the chip is selected and listens.
- If you set the CS pin to HIGH, the chip ignores what’s happening on the bus. The specific voltages depend on the logic levels of the devices.
Full Duplex: The Conveyor Belt
This is a unique feature of SPI. It is Full Duplex.
A UART with TX and RX lines can also be full duplex. In SPI, the separate MOSI and MISO lines allow shifting data in both directions simultaneously.
Imagine two shift registers connected in a loop. When the Master sends a bit over MOSI, the Slave simultaneously pushes a bit over MISO. It’s an exchange, a trade-off. Even if you only want to read data from the sensor, you are forced to send it “something” (usually zeros or junk) to “push” the data back.
Topology: How Do We Connect Multiple Devices?
If we want to connect 3 SPI sensors to the same Arduino:
- SCK, MOSI, and MISO are shared (they go in parallel to all sensors).
- CS (Chip Select) is individual. You need a separate wire from the Arduino for each sensor.
- Sensor 1 to Pin 10.
- Sensor 2 to Pin 9.
- Sensor 3 to Pin 8.
To talk to Sensor 1, you pull Pin 10 low, perform the transfer, and then pull it high again.
Disadvantage: The more devices, the more CS lines you need. In I2C, the two lines are shared, but the number of devices is limited by addresses, capacitance, and timing.
Push-Pull vs. Open-Drain (The Secret to Speed)
Why is SPI so fast and I2C so slow? Remember that I2C used Open-Drain (with pull-up resistors). Charging the wire’s capacitance using a resistor is slow (the signal rises like a shark fin curve).
SPI typically uses push-pull outputs. The edges can be faster than with a resistive pull-up, although wiring, loading, and reflections still distort the signal and can increase EMI emissions.
Protocol Comparison
Now that we know all three, which one do you choose for your project?
| Protocol | Speed | Wires | Topology | Ideal Use |
|---|---|---|---|---|
| UART | Low | 2 (RX/TX) | Point-to-Point | PC communication, GPS, Bluetooth. |
| I2C | Medium | 2 (SDA/SCL) | Bus (Addresses) | Slow sensors, RTC, gyroscopes. Easy wiring. |
| SPI | Very High | 3 + N (CS) | Bus (Chip Select) | TFT displays, SD cards, Ethernet, fast LED strips. |
Note on SPI Modes: You’ll sometimes see “SPI Mode 0, 1, 2, 3”. This defines whether we read the data when the clock rises or when it falls. The most common is Mode 0, but if a chip doesn’t work, check this in its datasheet.