Almost every electronics project eventually needs to connect two things together — a controller and a sensor, a controller and a display, or two boards talking to each other. Three communication standards handle the vast majority of these connections: I2C, SPI, and UART. Each one solves the problem differently, and picking the right one (or recognizing which one a module already expects) makes wiring and debugging significantly easier.
Why Communication Protocols Matter
A wire can only carry a signal that changes over time — on, off, on, off. A communication protocol is the agreed-upon set of rules both devices use to turn that stream of on/off signals into meaningful data: which wire means what, how fast the signal changes, and how each side knows when a message starts and ends. Without an agreed protocol, two devices wired together are just electrically connected — they aren't actually talking to each other.
I2C: Shared Bus, Simple Wiring
I2C (Inter-Integrated Circuit) uses just two signal wires — SDA (data) and SCL (clock) — plus power and ground, and multiple devices can share the same two wires at once. Each device on the bus has its own address, so the controller can talk to several sensors or modules using only two pins total, regardless of how many devices are connected.
This makes I2C especially convenient for projects with several low-speed sensors: an environmental sensor, a real-time clock, and a small display can all share the same two wires, as long as none of them have conflicting addresses (a common practical issue worth checking before wiring anything up). The tradeoff is speed — I2C is generally slower than SPI — and bus length; I2C is best suited to short, on-board or short-cable connections rather than long runs.
SPI: Fast, Point-to-Point
SPI (Serial Peripheral Interface) typically uses four wires: MOSI (controller-out, device-in), MISO (controller-in, device-out), SCLK (clock), and a separate chip-select (CS) line for each connected device. Unlike I2C's shared address-based bus, SPI identifies which device is being talked to by which chip-select line is active — meaning each additional device typically needs its own dedicated chip-select pin, even though the other three lines can usually be shared.
In exchange for using more pins, SPI is significantly faster than I2C and is the standard choice for high-speed peripherals — displays that need to refresh quickly, SD cards, and other modules where data throughput actually matters. If a module's datasheet specifically calls out a high refresh rate or large data transfers, there's a good chance it's built around SPI rather than I2C.
UART: Simple Serial, No Bus
UART (Universal Asynchronous Receiver-Transmitter) is the simplest of the three in concept: one wire for transmitting (TX) and one for receiving (RX), connected directly between exactly two devices, with no shared bus and no addressing scheme at all. Both sides just need to agree on a baud rate (how fast the signal changes) ahead of time.
Because UART is strictly point-to-point, it's a natural fit for connecting exactly two devices — a controller and a GPS module, a controller and a Bluetooth or cellular module, or two boards passing simple messages back and forth. It doesn't scale to multiple devices the way I2C does without additional hardware, but its simplicity makes it easy to debug: a logic analyzer or even a basic serial monitor can often show you exactly what's being sent.
Comparing Speed and Complexity
As a rough guide: UART is the simplest to understand and debug but only connects two devices at a time. I2C trades some speed for the convenience of multiple devices sharing just two wires. SPI trades extra wiring (a dedicated chip-select per device) for meaningfully higher speed. None of the three is universally "better" — the right choice depends on how many devices you're connecting, how much data needs to move, and how many pins you can spare.
Common Wiring Mistakes
A few mistakes account for the majority of "it's not working" moments with these protocols. Crossed TX/RX lines on UART — connecting TX to TX instead of TX to RX — is one of the most common; the two lines need to cross, not run parallel. On I2C, two devices sharing the same default address on the same bus will conflict, so it's worth checking a module's datasheet or documentation for its address (and any address-selection jumpers) before assuming it'll coexist with another device. On SPI, forgetting that each device typically needs its own chip-select line — and wiring several devices' CS pins together by mistake — is a frequent source of confusing, intermittent-looking failures. Voltage mismatches are a factor across all three: mixing 3.3V and 5V logic devices on the same bus without any level shifting is a common cause of unreliable or damaged connections.
Choosing the Right Interface for Your Project
In practice, you often won't be choosing the protocol from scratch — a given sensor or display module is usually built around one specific interface, and that decision is made for you by the module itself. What this knowledge actually helps with is reading a module's specifications before you buy: recognizing whether "I2C," "SPI," or "UART" in a listing means it'll share pins easily with the rest of your project, need dedicated wiring, or require you to check for address conflicts. For a closer look at what else to check on a listing before buying a sensor module, see our guide to reading a sensor module listing. Once you know which interface a project's components need, browsing sensors or displays by category makes it easier to confirm compatibility before you buy.