In short: A UART frames each byte with a start bit, optional parity, and stop bit(s), and both ends agree on a baud rate in advance; reliable links keep the cumulative baud mismatch under roughly ±2%, which receivers achieve by oversampling the line (commonly 16×) and sampling each bit near its center.
The UART (Universal Asynchronous Receiver/Transmitter) is the workhorse of embedded serial communication, yet most framing and timing bugs trace back to two misunderstood ideas: how a byte is framed, and how much baud error a link can tolerate. If you have already read our primer on the UART communication basics, this article digs into the timing mathematics that decides whether your link is rock-solid or silently corrupting every hundredth byte.
Why asynchronous means "no shared clock"
Unlike SPI or I²C, a UART sends no clock line. The transmitter and receiver each run from their own oscillator and simply agree on a bit period beforehand. At 115200 baud, one bit lasts 1/115200 s ≈ 8.68 µs. The receiver must recover byte boundaries from the data alone, so the protocol embeds explicit markers in every frame.
Framing: start, data, parity, stop
A UART frame is built from four parts, transmitted least-significant-bit first for the data payload:
- Start bit — a single low (0) bit. The idle line sits high, so a high-to-low edge tells the receiver "a byte is beginning." This edge is the only synchronization event the receiver gets.
- Data bits — typically 8, but 5–9 are legal. 7-bit data was common for ASCII text links; 9-bit framing supports address/multidrop schemes (RS-485).
- Parity bit — optional error detection. Even parity makes the count of 1s (data + parity) even; odd makes it odd. It catches any single-bit flip but is blind to two simultaneous flips.
- Stop bit(s) — one or two high bits that guarantee a return to idle, giving the receiver a known resting state before the next start edge.
The shorthand 8N1 means 8 data bits, No parity, 1 stop bit — the near-universal default. 7E1 means 7 data, Even parity, 1 stop. An 8N1 frame costs 10 bit-times per byte (1 start + 8 data + 1 stop), so a 115200-baud link carries at most 11,520 bytes/s, not 14,400 — a 20% framing overhead people routinely forget when sizing buffers.
Rule of thumb: divide the baud rate by 10 to get the maximum byte throughput of an 8N1 link. 9600 baud ≈ 960 bytes/s.
Oversampling: how the receiver finds the bit center
A classic UART receiver runs an internal clock at 16× the baud rate. When it detects the falling start edge, it waits 8 ticks to land in the middle of the start bit, confirms the line is still low (rejecting noise glitches), then samples every subsequent bit at 16-tick intervals — always aiming for the center, where the signal is most settled and furthest from the edges where the two clocks disagree.
Center sampling is what buys the link its error budget. If both clocks were perfect, you could sample anywhere. Because they are not, sampling at the center means the accumulated timing error over a whole frame has to grow to half a bit before the sample point drifts off the correct bit — this is the heart of the tolerance calculation below.
Baud error tolerance — the real math
Because the receiver only re-synchronizes on the start edge, timing error accumulates across the frame. The worst-case sample is the last bit. For an 8N1 frame the last data bit is the 9th bit after the start edge; the receiver aims for its center, i.e. 9.5 bit-times from the start edge. If the combined transmitter+receiver clock mismatch shifts that point by half a bit, you sample the wrong bit.
Half a bit out of 9.5 bits is ≈ 5.3% total budget. Split between two devices and allowing margin for edge jitter and the receiver's own ±1-tick quantization (1/16 ≈ 6.25% of a bit), designers target well under that. The widely used guideline:
| Frame format | Bits after start edge | Theoretical max mismatch | Safe design target |
|---|---|---|---|
| 8N1 | 9.5 (last-bit center) | ≈ ±5.3% | ±2% |
| 8E1 (parity) | 10.5 | ≈ ±4.8% | ±2% |
| 8N2 (2 stop) | 10.5 | ≈ ±4.8% | ±2% |
This is why internal RC oscillators (±1–2% untrimmed, worse over temperature) are marginal for UART, and why USB-to-serial and most MCUs use a crystal (±50 ppm = ±0.005%). Two ±2% clocks drifting in opposite directions already eat the entire 8N1 budget.
Baud rate generation and quantization error
You rarely get the exact baud rate you ask for. A UART divides a peripheral clock by an integer (sometimes fractional) divisor: divisor = round(f_clk / (16 × baud)). The achievable baud is then f_clk / (16 × divisor), and the rounding introduces its own error on top of oscillator tolerance.
Concrete example: an 8 MHz clock targeting 115200 baud needs divisor = 8,000,000/(16×115200) = 4.34, rounded to 4. The actual rate becomes 8,000,000/(16×4) = 125,000 baud — a +8.5% error that blows the budget completely. The same chip at 9600 baud gives divisor 52.08 → 52 → 9615 baud, only +0.16%. This is exactly why "magic" crystal frequencies like 1.8432, 3.6864, 7.3728, 11.0592, and 14.7456 MHz exist: each divides cleanly into standard baud rates with zero quantization error. Vendor tools (STM32CubeMX, the configurators in Synopsys DesignWare UART IP, or Cadence/Siemens verification IP for SoC UART blocks) report this percentage so you can verify it in silicon sign-off rather than discover it on the bench.
Practical debugging checklist
- Garbage at one rate, clean at a lower one — almost always baud quantization error. Recompute the divisor error; switch to a crystal frequency that divides cleanly.
- Framing errors (stop bit read as 0) — accumulated drift or a mismatched stop-bit count, or the two ends disagree on data-bit width.
- Occasional single-byte corruption — noise on the line; enable parity, add a stop bit, or slow down. A logic analyzer decoding the raw waveform (versus the UART's own decode) tells you whether the bits on the wire are wrong or the sampling is.
- First byte lost after idle — the receiver missed the start edge during a mode change; check break detection and that the line truly idles high.
Teams building custom UART blocks in RTL should also validate the oversampling state machine against corner-case baud mismatches in simulation — our applied courses walk through exactly this, and for hands-on silicon design work Avecas design services runs the same flows on production SoCs. For a refresher on the physical signalling side, see our note on RS-232 vs RS-485 signalling.
Want to design, simulate, and verify a UART from the register map up? Our Embedded & VLSI courses on CourseTron take you from framing theory to a verified RTL block.
FAQ
How much baud rate mismatch can a UART tolerate?
Theoretically about ±5% for a standard 8N1 frame (half a bit over 9.5 bit-times), but good designs keep the combined transmitter + receiver error under ±2% to leave margin for jitter and sampling quantization.
Why is 8N1 the default framing?
Eight data bits carry a full byte, no parity keeps throughput at the full 10-bits-per-byte rate, and one stop bit is the minimum that guarantees a clean return to idle. It is the best balance of efficiency and robustness for modern, low-noise links.
What does 16× oversampling actually do?
It lets the receiver detect the start edge precisely and sample each bit at its center (tick 8 of 16), maximizing the timing margin before accumulated clock drift pushes the sample point onto the wrong bit.
Why do people use crystals like 11.0592 MHz?
These frequencies divide evenly by 16 into standard baud rates (9600, 115200, …), giving zero baud-rate quantization error. An arbitrary clock like 8 MHz can produce multi-percent errors at high baud rates that corrupt the link.