I2C vs SPI vs UART: Embedded Serial Protocols Interview Interview Prep

Embedded serial protocols for interviews — I2C (open-drain, pull-ups, clock stretching), SPI (4-wire, CPOL/CPHA modes, chip-select), UART (async framing, baud, flow control), and bring-up debug gotchas.

Quick answer

Embedded serial protocols are the short-range, board-level buses firmware uses to talk to peripherals, and the three that dominate interviews are I2C, SPI, and UART.

Interviewers ask about I2C, SPI, and UART because almost every embedded project talks to a sensor, memory, display, or radio over one of them, and the bugs are concrete and hard to fake.

Editorial review

Written by

CompoundLearn editorial team

Wireless / RF / hardware engineering

Reviewed by

CompoundLearn editorial team

Wireless / RF / hardware engineering

Last reviewed

Built from curated topic maps, editorial validation, and subject-matter review so the page stays aligned with the interview intent and the current content pipeline.

Key points

  • I2C is a two-wire (SCL/SDA) open-drain addressed bus that needs pull-up resistors; speeds are 100 kHz (standard), 400 kHz (fast), and 1 MHz (fast-mode-plus) — best when pin count matters more than throughput.
  • SPI is a four-wire full-duplex bus (SCLK, MOSI, MISO + one chip-select per device) running tens of MHz — best for displays, ADCs, and flash, at the cost of a CS line per peripheral.
  • UART is asynchronous and point-to-point with no shared clock: start/data/parity/stop framing, matched baud on both ends, optional RTS/CTS or XON/XOFF flow control.
  • SPI has four modes from CPOL (clock idle level) and CPHA (sampling edge); master and slave must use the same mode or every byte is shifted and reads return garbage.
  • I2C clock stretching lets a slave hold SCL low to pause the master; controllers that ignore it corrupt transfers — a common "works on one MCU, not another" failure.
  • The canonical bring-up bugs are: dead I2C bus from missing pull-ups, NACK from a wrong address, SPI garbage from a CPOL/CPHA or bit-order mismatch, and UART gibberish from a baud mismatch.
  • The interview differentiator is reasoning about the electrical layer and reading a logic-analyzer decode to map symptom to root cause — not reciting register names.

What it is

Embedded serial protocols are the short-range, board-level buses firmware uses to talk to peripherals, and the three that dominate interviews are I2C, SPI, and UART. I2C is a two-wire, open-drain, addressed bus (SCL clock, SDA data) that connects many low-speed devices with just two pins and pull-up resistors; SPI is a faster four-wire, full-duplex bus (SCLK, MOSI, MISO, plus a chip-select per device) for higher-throughput parts like displays and flash; UART is an asynchronous, clockless, point-to-point link that exchanges a byte stream between two devices using matched baud rates and start/stop framing. They are not interchangeable — each makes a different tradeoff among pin count, speed, duplexing, addressing, and topology. The defining details are electrical and timing-level. I2C's open-drain wiring means devices only pull low, which is exactly what enables wired-AND arbitration and clock stretching, and is why pull-up sizing matters. SPI's behavior is governed by CPOL and CPHA, the four modes that set clock idle level and sampling edge, so a mismatch silently corrupts data. UART has no clock at all, so a baud or clock-divisor error drifts the sampling point and garbles the frame. Knowing these mechanisms — and how to bring a bus up and debug it — connects directly to the MCU and driver layer you program (see /topics/c-cpp-for-embedded-interviews, /topics/arm-cortex-architecture-for-embedded, /topics/embedded-linux-and-device-drivers).

Why interviewers ask

Interviewers ask about I2C, SPI, and UART because almost every embedded project talks to a sensor, memory, display, or radio over one of them, and the bugs are concrete and hard to fake. A candidate who can explain why I2C needs pull-ups, what open-drain buys you, and how clock stretching works has clearly driven real hardware; one who only memorized that "I2C uses two wires" has not. The questions are also a fast filter for systems judgment: choosing the right bus for a part — pins versus speed versus topology — shows the candidate reasons about constraints rather than reaching for a default (see /topics/embedded-engineer-interview-signals). The debug angle is just as revealing. Real bring-up failures map cleanly to these protocols: a dead I2C bus from missing pull-ups, a NACK from the wrong address, SPI garbage from a CPOL/CPHA mismatch, UART gibberish from a baud error. Asking a candidate to walk through diagnosing a non-responding sensor — put a logic analyzer on the lines, check idle levels and the clock, decode the address and ACK — separates engineers who can methodically isolate a hardware-software fault from those who only know the API. That practical, evidence-driven debugging is exactly the signal firmware interviews are built to surface (see /topics/c-cpp-for-embedded-interviews, /topics/arm-cortex-architecture-for-embedded).

Common mistakes

The most common mistake is treating the three buses as interchangeable and naming a default instead of justifying the choice on pins, speed, duplex, addressing, and topology. A second is forgetting that I2C is open-drain: candidates omit pull-ups, do not know why they are required, or cannot reason about pull-up sizing versus bus capacitance and speed — the single most frequent cause of a dead bus on bring-up. A third is mishandling SPI modes: not knowing what CPOL and CPHA select, assuming mode 0 always, or ignoring bit order and the slave's maximum clock, then being baffled when reads come back shifted or all 0xFF. A fourth is ignoring I2C clock stretching, so a slave that holds SCL low corrupts transfers on a controller that does not check for it — the classic "works on one MCU but not another." A fifth is UART baud and framing errors: mismatched baud, a wrong clock divisor, or missing flow control, all of which yield consistent gibberish or dropped bytes under load. Finally, many candidates skip the physical layer entirely — they cannot describe putting a logic analyzer on the lines, checking idle levels and the clock, and reading ACK/NACK and addresses off a decoded capture — which is precisely the methodical debugging interviewers want to see.

Frequently asked questions

When should you choose I2C, SPI, or UART for a peripheral?
Match the bus to the constraint. I2C is a two-wire (SCL, SDA) addressed bus: it scales to many devices on shared lines with only two pins, which is ideal for low-speed sensors, EEPROMs, and configuration ports where pin count matters more than throughput (standard 100 kHz, fast 400 kHz, fast-mode-plus 1 MHz). SPI is a faster four-wire full-duplex bus (SCLK, MOSI, MISO, plus one chip-select per device): pick it for displays, ADCs, and flash where you need tens of MHz, but it costs a dedicated CS line per peripheral. UART is asynchronous and point-to-point with no shared clock: use it for a console, a modem/GPS module, or a board-to-board link where two devices just need a byte stream. In interviews, name the tradeoff explicitly — pins versus speed versus topology — rather than reciting one default (see /topics/c-cpp-for-embedded-interviews).
Why does I2C need pull-up resistors and what value should they be?
I2C lines are open-drain: a device can only pull SCL or SDA low, never drive them high, so an external pull-up resistor restores the line to the high (idle) state. This is what lets multiple masters and slaves share a wire without contention — if two devices drive at once, the low always wins (wired-AND), so collisions are non-destructive and arbitration is possible. The pull-up value is a tradeoff between rise time and current: too large and the RC formed by the resistor and total bus capacitance makes the rising edge too slow for the clock rate; too small and the open-drain transistor cannot sink enough current to reach a valid low. Typical values run a few kilohms (often around 4.7k at 100 kHz, lower for 400 kHz or high bus capacitance). A dead bus on bring-up is very often missing or doubled pull-ups (see /topics/embedded-engineer-interview-signals).
What are SPI modes and how do CPOL and CPHA work?
SPI timing is defined by two bits, giving four modes (0 through 3). CPOL (clock polarity) sets the idle level of SCLK: CPOL=0 idles low, CPOL=1 idles high. CPHA (clock phase) sets which clock edge samples data: CPHA=0 samples on the first (leading) edge and shifts on the second, CPHA=1 samples on the second (trailing) edge. Mode 0 (CPOL=0, CPHA=0) and mode 3 (CPOL=1, CPHA=1) are the most common. The practical interview point is that master and slave must agree on the same mode or every byte is shifted by an edge and you read garbage. When a SPI peripheral returns 0xFF or 0x00 or shifted data on bring-up, a CPOL/CPHA mismatch is the first thing to check, alongside bit order (MSB vs LSB first) and the clock frequency the slave can tolerate (see /topics/arm-cortex-architecture-for-embedded).
What is I2C clock stretching and why does it break some controllers?
Clock stretching is how an I2C slave tells the master to wait: the slave holds SCL low after an edge, pausing the clock until it has processed a byte or prepared data. Because SCL is open-drain, any device on the bus can hold it low, and a compliant master must detect that SCL did not rise when released and delay the next bit. The trouble is that some controllers — especially bit-banged GPIO masters and certain hardware blocks — do not check whether SCL actually went high before continuing, so they clock past a stretching slave and corrupt the transfer. Sensors and microcontroller-based slaves stretch frequently. In interviews this surfaces as "why does this sensor work on one MCU but not another," and the answer is missing clock-stretch support. The fix is enabling stretch handling in hardware or adding the SCL-release check in software (see /topics/rtos).
How does UART framing work and why do baud rates have to match?
UART is asynchronous: there is no shared clock, so each side runs its own clock and agrees in advance on the bit rate (baud). A frame is a start bit (line pulled low), then data bits (typically 8), an optional parity bit, and one or more stop bits (line high). The receiver detects the falling start edge, then samples each bit at the middle of its expected window based on the agreed baud. If the two clocks differ by more than a few percent, sampling drifts across the frame and the last bits land in the wrong slots, producing garbage or framing errors. That is why a baud mismatch (or a wrong system clock that throws off the divisor) yields consistent gibberish — classic 9600-vs-115200 garble. Parity catches single-bit errors; flow control (RTS/CTS hardware or XON/XOFF software) prevents a fast sender from overrunning a slow receiver (see /topics/c-cpp-for-embedded-interviews).
How do you debug a non-working serial bus during board bring-up?
Start at the physical layer and work up. Put a logic analyzer or scope on the lines first: confirm the clock is present and at the expected frequency, that idle levels are right, and that edges are clean. For I2C, verify both lines idle high — a line stuck low usually means a missing pull-up or a slave holding the bus (a wedged slave can need a clock-pulse recovery sequence). For SPI, check that chip-select actually asserts (active-low) around the transfer and that CPOL/CPHA and bit order match. For UART, check idle-high, the start-bit edge, and measure the bit width to confirm baud. Then decode: most analyzers will interpret I2C/SPI/UART, so you can read the address, ACK/NACK, and payload directly and compare against the datasheet. Reading ACK/NACK, wrong-address, and shifted-data symptoms off a decoded capture is a core firmware-debug signal interviewers look for (see /topics/embedded-engineer-interview-signals, /topics/embedded-linux-and-device-drivers).
How should an embedded candidate prepare serial-protocol questions?
Be able to compare the three buses on pins, speed, duplex, addressing, and topology, and justify a choice for a concrete part — not just name a favorite. Know the electrical reality: I2C open-drain plus pull-ups and the wired-AND that enables arbitration and clock stretching; SPI four wires, full-duplex shift register, and one chip-select per device; UART asynchronous framing with start/stop/parity and matched baud. Memorize the four SPI modes and what CPOL/CPHA actually select. Practice diagnosing the canonical failures: dead I2C bus from pull-ups, NACK from a wrong address, SPI garbage from a mode mismatch, UART gibberish from baud mismatch. Finally, be ready to read a logic-analyzer capture and map symptoms to root cause. Tie it back to the MCU peripherals and driver layer you will actually program (see /topics/arm-cortex-architecture-for-embedded, /topics/c-cpp-for-embedded-interviews, /topics/embedded-linux-and-device-drivers).

Related topics

Essential AI-Native Skills for I2C vs SPI vs UART: Embedded Serial Protocols Interview

Modern engineering work increasingly uses AI tools for design and code review, debugging, documentation, test and testbench generation, and workflow automation. The goal is not to let AI replace engineering judgment — it is to move faster while keeping verification discipline.

  • Use AI to explain unfamiliar code, logs, waveforms, datasheets, or test failures.
  • Break large problems into small, reviewable steps you can verify independently.
  • Ask AI for hypotheses, then validate them against tests, measurements, simulations, or lab data.
  • Version-control your analysis scripts, testbenches, and configs — keep changes small and reviewable.
  • Document your assumptions, design tradeoffs, and debugging decisions.
  • Verify AI output before trusting it: run the checks that fit the domain — unit tests, linters, simulations, or bench/lab measurements.
  • Review AI output for correctness, edge cases, and real-world consequences.

I2C vs SPI vs UART: Embedded Serial Protocols Interview — coming to the question bank

The adaptive practice engine is already live for core wireless, RF, and ML systems. I2C vs SPI vs UART: Embedded Serial Protocols Interview isn't covered in the question bank yet — get notified when it's added.

One email when this topic launches. Nothing else. Unsubscribe in one click.