Skip to content

Communication Protocols interview questions

The buses that connect parts, and how they fail.

Practice all 10, gradedOne at a time. Free, no account.

What interviewers probe

  • SPI
  • I2C
  • UART
  • CAN Bus
  • Protocol Debugging
  • Ethernet & High-Speed Serial

Builds on Logic Families & Level Shifting, Termination Strategies, Probing Technique, Transmission Lines.

10 questions, easiest first

  1. 1A board uses its microcontroller's internal RC oscillator (no crystal) to generate a UART signal at 115200 baud. Right after power-up, the text on your terminal reads perfectly. After the board has been running for a minute or two, the output degrades into garbled characters and stays that way. What's the most likely explanation, and how would you confirm it on the bench?intro

    This is a common failure mode with low-cost microcontrollers that skip the external crystal to save BOM cost.

    Answer this one, graded
    Or just show what a strong answer covers

    Internal RC oscillators drift with temperature, and self-heating as the chip runs pushes the clock frequency away from its cold value. Since the UART baud clock is derived from that oscillator, the actual baud rate slowly walks outside the roughly 2-3% tolerance window the receiver can handle, so bit sampling starts landing on the wrong bit and characters garble. To confirm it, I'd put a scope or logic analyzer on the TX line and measure actual bit width right after power-up versus a few minutes in -- if it's shifted, that confirms drift. I could also correlate with board temperature using a thermocouple or IR camera. The fix is either an external crystal/oscillator, an oscillator trim/calibration routine, or just dropping to a lower baud rate that has more margin.

    • Identifies oscillator drift as root cause — States that the internal RC oscillator's frequency shifts as the chip self-heats, pushing the real baud rate outside the UART's tolerance window.
    • Explains why the error is intermittent, not present at power-up — Connects the delayed onset of garbling to gradual temperature rise rather than an immediate baud mismatch.
    • Proposes a concrete bench verification — Describes measuring actual bit width on a scope or logic analyzer over time, or logging board temperature against error onset.
    • Suggests a fix — Mentions using an external crystal/reference, trimming the oscillator, or reducing baud rate for margin.

    Where answers go wrong: Jumping straight to 'wrong baud rate' without explaining why it would start working and then fail · Blaming the USB-to-serial adapter without ruling out the RC oscillator · Not proposing any way to actually verify the hypothesis on the bench

  2. 2You wire up a new SPI sensor exactly per its datasheet, which specifies SPI Mode 2 (CPOL=1, CPHA=0). Your microcontroller's SPI peripheral, however, is left at its default of Mode 0 (CPOL=0, CPHA=0). You power up and start reading continuously -- the clock and chip-select lines look completely clean on the scope, but every byte you read back is nonsense and doesn't correlate to any sensible sensor value. Walk me through, from the bus's point of view, why this happens.intro
    Answer this one, graded
    Or just show what a strong answer covers

    CPOL sets whether the clock idles high or low, and CPHA sets whether data is shifted out on the leading or trailing edge and sampled on the other. In Mode 2 the slave is shifting data out on one edge expecting to be sampled on the opposite edge, but my Mode-0 master is sampling on the wrong edge relative to that -- so it's often latching MISO mid-transition or one bit-time off. The clock and CS timing themselves are fine, which is why they look normal on the scope; the actual data value at the sample instant is what's wrong. I'd confirm by overlaying MOSI/MISO against CLK on the analyzer and checking which edge the slave is actually changing data on versus which edge my peripheral is configured to sample -- if they're on the same edge instead of opposite edges, that's the mismatch, and I fix it by setting CPOL=1, CPHA=0 to match the datasheet.

    • Defines CPOL and CPHA functionally, not just by name — Answer explains CPOL as idle clock level and CPHA as which edge triggers shift-out vs sample-in, not just recites acronym expansion.
    • Explains the specific failure mechanism — Explains that mismatched mode causes the master to sample at the wrong point in the data's valid window (e.g., during a transition), producing corrupted or shifted bits every transaction.
    • Notes clock/CS can look 'normal' while data is still wrong — Recognizes that CLK and CS timing can appear perfectly clean on a scope even though the mode mismatch is purely about the sampling edge relationship, so a normal-looking clock doesn't rule this out.
    • Describes a concrete debug step — Proposes actually overlaying MOSI/MISO against CLK edges on a scope or analyzer to see which edge carries valid data versus which edge the master samples.

    Where answers go wrong: Saying 'CPOL and CPHA didn't match' without explaining what that actually does to the sampled bit · Assuming the problem must be wiring or chip select since those 'look fine' on the scope · Confusing mode mismatch with baud/clock rate mismatch · Not connecting the mismatch to a specific observable symptom (shifted or inverted bits)

  3. 3You're sizing the pull-up resistors for a standard-mode I2C bus (100 kHz) with a total bus capacitance of 400 pF and a 3.3V supply. The I2C spec requires the rise time on SDA/SCL to be under 1000 ns. What's the largest pull-up resistance you can use while still meeting that rise time spec?easy

    Use the standard approximation t_rise ~= 0.8473 * R_pullup * C_bus for an RC-charged open-drain line.

    Answer this one, graded
    Or just show what a strong answer covers

    Rise time on I2C is set by the pull-up resistor charging the bus capacitance, so t_rise is about 0.8473*R*C. Solving for R: R = t_rise / (0.8473*C) = 1000ns / (0.8473*400pF) which comes out to roughly 2.9-3 kohm. That's the maximum I can use and still meet the 1000ns spec -- anything larger and the rising edge won't reach the threshold in time, risking misread bits at 100kHz. I'd probably pick something smaller than that max, like 2.2k or 2k, for margin, but I also have to watch the tradeoff: smaller resistors mean more static current through the pull-up when the line is pulled low, and the open-drain driver has to be able to sink that current within its rated low-level output voltage.

    • Sets up the RC rise time relationship — Uses or derives the relationship between rise time, resistance, and bus capacitance rather than guessing a number.
    • Arrives at a resistance near 2.9-3.0 kohm — Solves for R given t_rise=1000ns and C=400pF, landing close to 2950 ohms.
    • Notes this is a maximum, not a fixed value — States that this is the upper bound and a smaller resistor would also work but draws more current.
    • Mentions the competing constraint — Notes that too small a resistor increases static current draw and low-level output current requirements on the open-drain drivers.

    Where answers go wrong: Forgetting that this is a maximum bound, not the resistor value to actually use · Ignoring the 0.8473 constant and using a plain RC=tau approximation without justification · Not connecting the answer back to why smaller resistors aren't free (current draw, drive strength limits)

  4. 4You've wired an SPI sensor to a microcontroller. On the scope, the clock is toggling cleanly and chip select is asserted for the whole transaction, but every byte you read back looks like it's shifted by one bit -- as if the MSB from the next byte leaked into the current one. What's the likely cause, and how would you fix it?easy
    Answer this one, graded
    Or just show what a strong answer covers

    A consistent one-bit shift on every byte, with clean clock and CS, is the classic signature of a CPOL/CPHA mismatch -- the master is sampling MISO on the wrong clock edge relative to when the slave is actually presenting valid data. I'd check the device's datasheet timing diagram to see which edge data changes on versus which edge it should be sampled on, then compare that against the scope trace of MOSI/MISO relative to SCLK. Fix is just setting the SPI peripheral's mode register to match the device's expected mode -- one of the four CPOL/CPHA combinations. If I had multiple devices needing different modes on one bus, I'd reconfigure the SPI peripheral's mode setting before each transaction.

    • Identifies CPOL/CPHA mismatch as the cause — States that sampling on the wrong clock edge/phase causes a consistent one-bit shift rather than random corruption.
    • Distinguishes this from a wiring or noise problem — Explains why a consistent, repeatable one-bit shift points to a mode/timing issue rather than a loose connection or ringing.
    • Describes how to confirm on the scope — Mentions checking exactly when MOSI/MISO data transitions relative to the clock edge against the device's datasheet timing diagram.
    • Gives the fix — States that the fix is matching SPI mode (CPOL/CPHA) between master and slave configuration.

    Where answers go wrong: Blaming it on cable length or signal integrity without checking the mode settings first · Not recognizing that a *consistent* one-bit shift (not random) is the signature of a mode mismatch · Confusing chip select framing issues with clock edge sampling issues

  5. 5You're configuring a UART for 115200 baud off a 16 MHz system clock through an integer baud-rate divider. The closest achievable divider actually yields 117647 baud instead of exactly 115200. For an 8-N-1 frame (1 start bit, 8 data bits, 1 stop bit -- 10 bit times total), calculate the percent baud error between transmitter and receiver. Then tell me: given that a receiver typically needs to stay within about half a bit-time of accumulated drift by the last bit of the frame to sample it correctly, is this link going to work reliably?easy
    Answer this one, graded
    Or just show what a strong answer covers

    Percent error is (117647-115200)/115200, which comes out to about 2.12%. What matters for reliability isn't that error compounding forever -- UART resyncs at every start bit's falling edge, so I only need to worry about drift accumulated across one 10-bit frame. At roughly 2.1% error over 10 bit-times, the sampling point has drifted by about 0.21 of a bit period by the last bit, which is comfortably under the roughly half-bit-period budget most UARTs can tolerate. So this should work reliably in practice, though it's not as much margin as I'd want if I also had electrical noise or jitter on the line -- I'd rather pick a divider that gets closer to nominal if one's available.

    • Correct percent error calculation — Computes (117647-115200)/115200*100 ~ 2.1-2.2% with the arithmetic shown.
    • Ties tolerance to frame length, not absolute clock error alone — Explains that what matters is how much the sampling point has drifted by the last bit of the 10-bit frame, since UART resyncs every start bit.
    • Reaches a reasoned pass/fail judgment — States that ~2.1% is within (or right at the edge of) the typical ~2-3% tolerance for reliable sampling and justifies it, rather than giving an unsupported yes/no.

    Where answers go wrong: Computing the error the wrong way round (nominal-actual)/actual instead of relative to nominal · Treating the error as accumulating across an entire multi-byte message instead of resetting each frame · Giving a bare 'yes it works' or 'no it doesn't' without connecting to the half-bit-drift reasoning · Forgetting that only 9 of the 10 bit times matter for drift (drift is measured to the point of sampling the last data/stop bit, not from a hypothetical 11th bit)

  6. 6During bring-up, a power glitch happens mid-transaction on an I2C bus. Afterward, the bus is completely stuck: SDA reads low all the time, every subsequent transaction from the master times out or gets a NACK, and this persists even after a full firmware reset. Explain why this happens, and walk through how you would get the bus moving again -- both from the hardware side and the firmware side.medium
    Answer this one, graded
    Or just show what a strong answer covers

    A power glitch mid-transaction likely caught a slave device in the middle of driving SDA low, for example acknowledging a byte, and then the master reset without ever finishing that clock cycle. The slave is left holding SDA low waiting for a clock edge from the master that never comes, and since I2C is a shared open-drain bus, no amount of resetting the master's own firmware state changes what the slave is doing electrically. To recover, the standard procedure is to have the master manually toggle SCL up to nine times while watching SDA -- each clock should let the stuck slave shift out whatever bit it's holding, and once SDA goes high I issue a STOP condition to fully release the bus. Long term, I'd want a hardware mitigation too: either a reset line to slave devices, a bus watchdog that detects a stuck-low condition and forces a recovery, or building the clock-toggle recovery into the I2C driver itself so it runs automatically on timeout.

    • Explains why a firmware-only reset doesn't fix it — States that the master resetting doesn't affect a slave that's stuck holding SDA low, since the bus is a shared open-drain line and the slave's state is unaffected by the master's reset.
    • Describes the mechanism of the lockup — Explains that the slave was likely interrupted while driving SDA low (e.g. mid-ACK) and is waiting for clock edges that never came due to the glitch.
    • Describes the clock-toggle recovery sequence — Describes manually pulsing SCL (up to 9 clocks) while watching SDA to free the stuck slave, followed by issuing a STOP condition.
    • Mentions a hardware-side mitigation — Proposes at least one hardware safeguard such as a slave reset line, bus watchdog, or timeout circuit to prevent recurrence.

    Where answers go wrong: Assuming a firmware reset of the master will clear the bus, without recognizing the slave is the one stuck · Not knowing the manual clock-toggle recovery procedure at all · Proposing only a software fix with no discussion of preventing recurrence in hardware

  7. 7Two CAN nodes start transmitting at exactly the same time. Node A's 11-bit identifier is 0x1A3, and Node B's is 0x1A5. Walk through the arbitration process bit by bit and tell me which node wins and keeps transmitting, and why. Then explain: if this bus is missing its 120-ohm termination resistor at one end, what symptom would you actually expect to see, and under what bus conditions would it show up?medium

    Recall that in CAN, a dominant bit (0) always overwrites a recessive bit (1) when both are driven simultaneously, and lower numeric identifier value generally means higher priority.

    Answer this one, graded
    Or just show what a strong answer covers

    0x1A3 in 11 bits is 011 0100 0011, and 0x1A5 is 011 0100 0101. Comparing bit by bit from MSB down, they match until we get to the pair right before the last few bits -- specifically bit 2 from the end differs: node A has a 1 there where node B has a... actually let me just compare directly: 0x1A3 = ...0011, 0x1A5 = ...0101, so at the bit position where A has 0 and B has 1, since dominant(0) beats recessive(1), A wins that bit and keeps transmitting while B, seeing the bus dominant when it drove recessive, backs off. So node A, with the lower numeric ID, wins arbitration and gets priority, which is why lower CAN IDs are used for higher-priority messages. On termination: a missing 120-ohm resistor doesn't necessarily break the bus outright at low speed and light load -- reflections off the unterminated end degrade signal integrity and eat into noise margin. You'd typically see intermittent bit errors and increased bus-off events specifically under higher bus load, longer bus length, or higher bit rates where reflection settling time competes with the bit period, rather than a bus that fails every single transaction.

    • Converts both IDs to binary correctly — Correctly expands 0x1A3 and 0x1A5 to their 11-bit binary representations before comparing.
    • Identifies the exact bit where arbitration is lost — Finds the specific bit position where the two IDs first differ and correctly applies dominant-wins-over-recessive logic to determine node A wins.
    • States the correct winner with reasoning — Concludes Node A (0x1A3) wins because it has a dominant bit where Node B has a recessive bit at the first differing position.
    • Correctly characterizes the termination symptom — Explains that missing termination causes reflections that manifest as intermittent bit errors, worse under high load or with long stubs, rather than a bus that never works at all.

    Where answers go wrong: Assuming numerically higher ID wins arbitration instead of lower · Not walking through the bits explicitly and instead just asserting an answer · Claiming a missing terminator would make the bus completely non-functional in all conditions, rather than an intermittent, load-dependent failure

  8. 8A CAN node starts throwing transmit errors intermittently, and eventually its transmit error counter climbs past 255, pushing it into the bus-off state -- it stops transmitting entirely and drops off the network, while every other node keeps communicating normally. Walk me through what has to be physically happening on this node's transmissions to drive its error counter that high, and what has to happen afterward for the node to rejoin the bus.medium
    Answer this one, graded
    Or just show what a strong answer covers

    The error counter climbs from actual detected errors on that node's own transmissions -- most commonly a bit error, where it drives a dominant bit but reads back recessive (or vice versa), or an ACK error if no other node acknowledges its frame, or CRC/stuff errors. Each of those adds roughly 8 to the transmit error counter, and successful frames only subtract 1, so a node with a persistent local fault racks up errors much faster than it can recover. Once the counter passes 255 it goes bus-off -- that's a deliberate protection mechanism so one broken node can't keep corrupting traffic for everyone else. To come back, it can't just retry on its own; per spec it has to observe a set number of consecutive recessive bit sequences on an idle bus, confirming the bus is healthy, before it resets its counters and re-enables its transmitter. Since it's only this one node failing while the rest of the network is fine, I'd suspect something local to it -- missing or wrong termination causing reflections it can't tolerate, a wiring fault or short on its CANH/CANL pair, a failing transceiver, or its bit-timing/sample-point configuration being slightly off from everyone else's.

    • Explains what increments the error counter — Names at least one concrete CAN error type (bit error -- transmitted dominant read back as recessive or vice versa, ACK error, CRC error, stuff error) that would drive the counter up on repeated bad transmissions.
    • Explains why bus-off exists — States that bus-off is a deliberate protocol-level shutdown to stop a persistently faulty node from corrupting the shared bus for other nodes, not just an incidental failure.
    • Describes the recovery mechanism correctly — Mentions the node must see a defined amount of continuous recessive/idle bus activity before it can reset counters and resume transmitting, i.e. it can't simply retry on its own schedule.
    • Proposes plausible node-local root causes — Lists at least two concrete physical causes specific to that one node (bad termination/reflections, wiring fault, failing transceiver, mismatched bit timing) rather than a vague 'bus problem'.

    Where answers go wrong: Saying 'it lost arbitration too many times' -- arbitration loss is normal and doesn't drive the error counter up · Describing bus-off as a random crash rather than a deliberate protocol-mandated protection mechanism · Assuming the node can just immediately retransmit after bus-off without any recovery condition · Blaming the whole bus network when the fact that only one node fails points to something local to that node

  9. 9A board's Ethernet link light intermittently fails to come up, but only when the board is cold (just after power-on in a cool room); once it's been running a few minutes it links reliably every time. The PHY's status register reports 'no link partner detected' during the failures. Given the PHY/MAC split and the magnetics in the signal path, walk through where you'd look first, what you'd measure, and what you'd expect to see if your hypothesis is correct.hard
    Answer this one, graded
    Or just show what a strong answer covers

    Since the PHY itself is reporting 'no link partner detected,' the failure is happening during physical-layer link training/auto-negotiation, before any frames reach the MAC, so I wouldn't waste time in the driver or MAC-level code -- the MAC only sees a link-up bit and has no insight into why training failed. I'd suspect something in the analog path that's temperature-sensitive: the PHY's reference crystal or oscillator could be running out of frequency tolerance when cold, the magnetics (transformer) could have shifted inductance or increased insertion loss at low temperature affecting the fast link pulse amplitude, or bias/termination resistors near the PHY could be marginal cold. To isolate it, I'd try to reproduce the failure reliably with cold spray targeted at individual components -- PHY first, then magnetics -- while probing the reference clock frequency and the differential pair signal amplitude at the transformer with a scope, and reading the PHY's internal status/diagnostic registers if available. If cold-spraying just the PHY reproduces the failure and the reference clock frequency measures out of spec when cold, that points to the oscillator; if the differential signal amplitude at the transformer secondary drops out of spec when cold, that points to the magnetics.

    • Correctly scopes the problem to the PHY/analog side, not the MAC/software side — Explains that since the PHY reports 'no link partner detected,' the failure is in the physical layer training/negotiation process, and the MAC has no useful visibility into it.
    • Proposes at least two concrete temperature-sensitive suspects — Names specific components that could plausibly drift with cold temperature and affect link training, such as the reference crystal/oscillator, magnetics, or PHY bias/termination resistors.
    • Describes a way to reproduce and isolate the failure — Proposes a method like cold spray, chamber testing, or comparing PHY register states/clock measurements between the failing cold state and the working warm state.
    • Describes what evidence would confirm or rule out each hypothesis — States what a specific measurement result would look like if a given hypothesis is correct, e.g. reference clock frequency out of tolerance, or reduced signal amplitude at the transformer.

    Where answers go wrong: Jumping to 'it's a driver/firmware bug' despite the PHY register explicitly showing a link-negotiation failure, not a software issue · Naming only one vague possible cause without a way to test it · Ignoring the fact that the PHY, not the MAC, owns the physical link process and treating this as a purely digital/software debugging problem

  10. 10You have an I2C sensor that occasionally needs extra time to prepare a byte, so it holds SCL low (clock stretching) for up to 5ms during a read. Your master implementation has a bus timeout of 2ms: if it doesn't see the expected SCL/SDA states within that window, it aborts the transaction and resets its I2C peripheral. In testing, most reads succeed, but a small fraction fail -- and worse, occasionally the whole bus locks up afterward, requiring a power cycle to recover. Walk me through the failure chain here, and how you'd fix it robustly.hard
    Answer this one, graded
    Or just show what a strong answer covers

    Clock stretching means the slave is allowed to hold SCL low mid-byte while it gets a byte ready, and the master is supposed to just wait until SCL actually goes high again. My timeout is only 2ms but the slave can legitimately need up to 5ms, so some fraction of the time the master gives up and resets itself while the slave is still mid-transaction -- that explains the intermittent read failures right there, they're not real faults. The lockup is the worse consequence: when the master bails out and resets its own state machine, the slave doesn't know the transaction was abandoned. It can be left holding SDA low waiting to finish shifting out a bit or waiting for an ACK that never comes, and from the master's perspective on the next attempt that looks exactly like a stuck bus. The real fix is to set the timeout comfortably above the slave's documented worst-case stretch time so the master never aborts a legitimate stretch in the first place. But since bus lockups can also happen from real faults, I'd still add a proper I2C bus-recovery routine as a backstop -- toggling SCL up to nine times while watching SDA, then issuing a STOP condition, which is the standard way to force a wedged slave to release the bus without needing a full power cycle.

    • Explains clock stretching correctly — Describes that the slave can legitimately hold SCL low to delay the master, and the master must wait for SCL to release rather than assume a fixed timing.
    • Connects timeout value to the specific failure — Explicitly notes 2ms timeout < 5ms worst-case stretch means the master will sometimes abort mid-transaction during a legitimate stretch, not just during a genuine fault.
    • Explains the lockup mechanism, not just the failed reads — Explains how an abort/reset that isn't coordinated with the slave's state can leave the slave holding SDA low mid-byte, producing a bus that looks stuck on the next attempt.
    • Proposes both a root fix and a defensive recovery mechanism — Recommends raising the timeout above the datasheet's worst-case stretch time as the primary fix, and separately implementing a bus-clear/recovery sequence (extra SCL pulses plus STOP) as a safety net for genuine lockups, rather than proposing only one of the two.

    Where answers go wrong: Only suggesting 'increase the timeout' without explaining why the 2ms vs 5ms mismatch is the actual root cause · Treating the intermittent read failures and the full bus lockup as unrelated problems instead of one failure chain · Proposing a fix that just resets the master repeatedly without addressing that the slave can be left holding SDA low · Not mentioning the standard I2C bus-recovery technique (toggling SCL, issuing STOP) as a defensive backstop

Next topicLab Instrumentation

Interviewing for a specific role?

Paste the job description and we weight communication protocols against everything else the role needs.