Skip to content
RFrftools.io
ProtocolMay 7, 202612 min read

UART Baud Rates Explained: From Garbage Characters to Reliable Serial Links

A practical guide to UART baud rates — why 9600 and 115200 exist, how clock error causes framing failures, worked examples with real MCUs, and the 2% rule every embedded engineer needs to know.

Contents

The Moment Everyone Has Had

You wire up two boards. TX to RX, RX to TX, ground to ground. You flash your firmware, open the serial monitor, and... garbage. ÿÿÿÿ or ⸮⸮⸮⸮ or maybe nothing at all. You double-check the wiring. You swap TX and RX (everyone does this at least once). Still garbage.

Then someone asks: "what baud rate are you set to?"

And there it is. One side is talking at 9600, the other is listening at 115200. The electrical signals are perfect — voltage levels, wiring, everything checks out — but the two devices are speaking at completely different speeds. It's like trying to read a book while someone flips the pages at triple speed. The characters are all there; you just can't make sense of them.

This is the most common serial communication failure in embedded systems, and it's entirely preventable once you understand what baud rate actually means and why it matters so much for UART.


What Baud Rate Actually Is

Baud rate is the number of signal transitions — symbols — per second on the wire. For UART specifically, each symbol is one bit, so baud rate equals bit rate. When you set 115200 baud, you're telling the transmitter to change the line voltage every 1/115200 seconds, which works out to about 8.68 microseconds per bit.

Here's the critical thing: UART has no clock wire. Unlike SPI or I2C, there's no separate signal telling the receiver when to sample. Both sides independently generate their own timing from their own clocks. They just have to agree on the speed beforehand.

Think of it like two people reading a shared ticker tape. There's no bell that rings for each letter — they both just agreed to look at the next character every 8.68 microseconds. If one person's watch runs 5% fast, they'll eventually start reading the wrong characters. That's exactly what happens with UART when clocks don't match.

The receiver detects the start of a byte by watching for the start bit — a transition from high (idle) to low. Once it sees that falling edge, it starts its internal timer and samples the data bits at the expected intervals. If the baud rate is even slightly off, by the time it gets to bit 7 or the stop bit, it's sampling at the wrong moment.


The Standard Baud Rates (And Why Those Weird Numbers)

If you've worked with serial at all, you've seen the usual suspects:

Baud RateBit PeriodOrigin
7513.3 msTelegraph (Baudot code)
1109.1 msTeletype ASR-33
3003.33 msEarly acoustic modems
1200833 µs1200-baud modem era
2400417 µsV.22 standard
9600104 µsDe facto "safe default"
1920052.1 µs2× 9600
3840026.0 µs4× 9600
5760017.4 µsOddball (not 6× 9600)
1152008.68 µsStandard "fast" UART
2304004.34 µs2× 115200
4608002.17 µsPushing it for many MCUs
9216001.09 µsNear the limit
Why these specific numbers? They're historical accidents that stuck. 75 baud comes from the telegraph era — the Baudot code used 5-bit characters, and 75 baud gave operators time to read the printout. 110 baud was the Teletype Model 33's speed, set by the mechanical limitations of the print head. 300 baud was the first widely used modem speed (the acoustic couplers you'd jam a phone handset into). From there, each generation roughly doubled: 1200, 2400, 4800, 9600. These aren't powers of two, though — they're multiples of 300.

So why is 57600 in the standard set instead of 56400 (which would be a cleaner multiple)? It's 115200 / 2, and 115200 itself comes from the 8250 UART chip used in IBM PCs. The 8250 had a 1.8432 MHz oscillator, and with a divisor of 1, you got 115200 baud (1843200 / 16 = 115200). The divisor-of-16 oversampling is baked into the hardware.

The result: we're all still using baud rates dictated by a crystal frequency chosen in 1981.

Why 9600 Is The Universal Default

9600 baud is slow enough to work with almost any clock source, any wire length under a few meters, and any UART peripheral — even the most basic ones. It's the speed that "just works." GPS modules default to it. Bootloaders use it. When you don't know what speed a device speaks, try 9600 first.

But 9600 is also painfully slow for anything beyond short text messages. At 10 bits per frame (8N1 format), you get 960 bytes per second. Printing a 1 KB debug log takes over a second. That's why most development work uses 115200 — it's 12× faster and still reliable with any modern MCU crystal.


Worked Example: GPS Module Mismatch

Let's say you have a u-blox NEO-6M GPS module. It outputs NMEA sentences at 9600 baud by default. Your STM32 firmware accidentally configures USART2 at 115200. What happens?

The GPS sends a $ character (ASCII 0x24, binary 00100100). On the wire at 9600 baud, each bit is 104.17 µs wide. The full 10-bit frame (start + 8 data + stop) takes 1.042 ms.

But your STM32 is sampling at 115200 — expecting bits that are 8.68 µs wide. When it sees the start bit's falling edge, it starts sampling every 8.68 µs. In the time it takes the GPS to send ONE bit (104.17 µs), the STM32 samples 12 times. It reads 12 "bits" from what's actually a single bit.

The result: you see random-looking characters in your terminal. Not just wrong characters — completely unpredictable garbage, because the receiver is slicing the waveform into 12× more pieces than intended.

The fix: Match the baud rate. Set your STM32 to 9600 or reconfigure the GPS (via UBX protocol commands) to 115200. There's no negotiation, no auto-detect (in most cases) — both sides must be explicitly configured to the same speed.

Worked Example: High-Speed Sensor Data Logging

You're building a data logger that reads an accelerometer at 1 kHz (1000 samples per second). Each sample has X, Y, Z axes as 16-bit integers, plus a timestamp. You want to stream this over UART to an FTDI USB-serial adapter for PC capture.

Let's figure out what baud rate you need:

Step 1: Calculate the data payload.
  • 3 axes × 2 bytes each = 6 bytes per sample
  • 4 bytes for timestamp = 4 bytes
  • 2 bytes overhead (header + checksum) = 2 bytes
  • Total: 12 bytes per sample
Step 2: Calculate bytes per second.

12 bytes × 1000 samples/s = 12,000 bytes/second

Step 3: Convert to bits per second (accounting for UART overhead).

With standard 8N1 framing, each byte costs 10 bits on the wire (1 start + 8 data + 1 stop):

12,000 bytes × 10 bits/byte = 120,000 bits/second

Step 4: Choose a baud rate with margin.

You need at least 120,000 bps. The next standard rate up is 230400. But wait — can you use 115200? That gives you 115,200 bps on the wire, which is less than your 120,000 requirement. You'll lose data.

So 230400 it is — giving you 230,400 / 120,000 = 92% headroom. That's plenty of margin for interrupt latency, buffer management, and occasional burst traffic.

Alternatively, you could use 115200 if you reduce your sample rate to 960 Hz (115,200 / 12 / 10 = 960). In practice, I'd recommend 230400 with the full 1 kHz rate — the headroom lets your firmware breathe.

Use the UART Baud Rate calculator to verify the actual achievable rate and error for your specific MCU clock.


The 2% Rule — Clock Tolerance

Here's where UART gets tricky. Since there's no shared clock, both transmitter and receiver generate their baud rate from their own oscillators. If those oscillators drift apart, bits get misread.

The standard tolerance for reliable UART communication is ±2% cumulative error between both ends. In practice, most references recommend keeping each side under ±1%, so the worst-case total mismatch stays under 2%.

Why 2%?

UART receivers use 16× oversampling — they sample the line 16 times per bit period and use the middle samples (typically samples 7, 8, 9 out of 16) to determine the bit value. This gives some tolerance to timing drift.

For an 8N1 frame (10 bits total), the last bit sampled is bit #10 (the stop bit). The accumulated error by that point is:

Accumulated error=bit error×10 bits=0.5 bit (maximum)\text{Accumulated error} = \text{bit error} \times 10 \text{ bits} = 0.5 \text{ bit (maximum)}

If the total timing error causes the sampling point to drift by more than half a bit period by the end of the frame, you'll sample the wrong bit. Working backwards:

Max error per bit=0.510=5%\text{Max error per bit} = \frac{0.5}{10} = 5\%

But that's theoretical maximum with perfect start-bit detection. In practice, the start bit detection itself has ±0.5 sample uncertainty (out of 16 samples), eating into your margin. The real-world safe limit is about 3.75% total, and engineers use 2% as a conservative design rule.

What 2% Looks Like In Practice

At 115200 baud, a 2% error means the actual baud rate is somewhere between 112,896 and 117,504. The bit period is off by ±0.17 µs. Over a 10-bit frame, that accumulates to ±1.7 µs of drift — about 20% of a bit period. Still safe, but you're using up your margin.

At 9600 baud, 2% error is much less critical in absolute terms (±2.08 µs per bit, ±20.8 µs per frame) because the bit periods are so wide. This is another reason 9600 is the "safe" default — even terrible oscillators can hit it.


MCU Clock Sources and Baud Rate Error

Not all clocks are created equal for UART:

Crystal Oscillator (HSE)

Accuracy: typically ±20 ppm (0.002%). Essentially perfect for UART. Any standard baud rate will work with negligible error. This is what the ESP32, most STM32 dev boards, and Arduino Uno (16 MHz crystal) use.

Internal RC Oscillator (HSI)

Accuracy: ±1% to ±5% depending on temperature and voltage. The STM32's internal 8 MHz HSI is factory-trimmed to ±1% at 25°C, but can drift to ±2% over the full temperature range. The ATmega328P's internal 8 MHz RC oscillator is ±10% uncalibrated (!) but ±2% after factory calibration.

This is where things get dangerous. If both your transmitter AND receiver are using RC oscillators, you could have up to 4% total mismatch. UART will fail intermittently — working fine on the bench at room temperature, then dropping characters in the field when it's hot or cold.

Rule of thumb: If you're running UART above 9600 baud without a crystal, calculate your worst-case baud rate error using the UART calculator and verify it stays under 2%.

The BRR Divisor Problem

Even with a perfect crystal, you might not get an exact baud rate. The UART peripheral divides the clock by an integer (the BRR register) to generate the baud rate:

Actual Baud=fclk16×BRR\text{Actual Baud} = \frac{f_{clk}}{16 \times \text{BRR}}

If the division doesn't come out even, you get quantization error. For example, a 16 MHz clock trying to generate 115200 baud:

BRR=16,000,00016×115200=8.68\text{BRR} = \frac{16{,}000{,}000}{16 \times 115200} = 8.68

You can't load 8.68 into a register — it rounds to 9. The actual baud rate becomes:

Actual=16,000,00016×9=111,111 bps\text{Actual} = \frac{16{,}000{,}000}{16 \times 9} = 111{,}111 \text{ bps}

Error: (115200111111)/115200=3.55%(115200 - 111111) / 115200 = 3.55\%. That exceeds 2%. This specific combination of clock and baud rate won't work reliably without fractional divider support.

Some MCUs (STM32, SAM, nRF) have fractional BRR dividers that solve this. Others (ATmega) don't — you need to choose your crystal frequency carefully. The classic 7.3728 MHz and 11.0592 MHz crystals exist specifically because they divide evenly into standard baud rates.

CrystalBRR for 115200Actual BaudError
7.3728 MHz41152000.00%
8 MHz4.34 → 41250008.51%
11.0592 MHz61152000.00%
16 MHz8.68 → 91111113.55%
18.432 MHz101152000.00%
48 MHz26.04 → 261153850.16%
72 MHz39.06 → 391153850.16%
Notice the pattern: 7.3728, 11.0592, and 18.432 MHz all give zero error because they're multiples of 115200 × 16 × (some integer). The "round" frequencies like 8 and 16 MHz are actually worse for UART.

Modern STM32 and ESP32 chips use fractional dividers with 4–8 fractional bits, effectively eliminating this problem. But if you're working with an ATmega328P (Arduino Uno) at 16 MHz, that 3.55% error on 115200 is real. The Arduino bootloader actually uses 115200 and gets away with it because the FTDI chip on the other end is crystal-accurate and tolerant — but it's right at the edge.


Common Mistakes

1. Wrong Baud Rate In Code

The number one cause of serial garbage. Triple-check that both sides match. Common traps:

  • GPS modules default to 9600, not 115200
  • ESP32 boot ROM outputs at 74880 baud (a weird one)
  • Some Bluetooth modules (HC-05) use 38400 for AT commands but 9600 for data mode
  • Many sensors default to 9600 regardless of what the marketing says about "high-speed"

2. Software UART (Bit-Banging) Limitations

Software UART (Arduino's SoftwareSerial, for example) generates timing in software using delay loops. This means:

  • Interrupts can stretch bit timing unpredictably
  • Maximum reliable speed is typically 1920038400 baud
  • CPU load scales linearly with baud rate
  • Receiving while transmitting is often impossible
If you need 115200 or higher, use a hardware UART peripheral. Always.

3. Voltage Level Mismatch (Looks Like Baud Rate Problem)

A 3.3V UART talking to a 5V UART (or vice versa) can produce garbled output that looks exactly like a baud rate mismatch. The receiver's threshold voltage isn't being crossed cleanly, causing false start bits and corrupted data. Always check voltage compatibility before blaming the baud rate.

4. Forgetting UART Overhead

New engineers often calculate required bandwidth as data_rate / 8 and set that as the baud rate. But each byte costs 10 bits (8N1) or 11 bits (8E1) on the wire. The actual useful throughput of 115200 baud with 8N1 is:

Throughput=11520010=11,520 bytes/sec=11.25 KB/s\text{Throughput} = \frac{115200}{10} = 11{,}520 \text{ bytes/sec} = 11.25 \text{ KB/s}

Not 14.4 KB/s (which would be 115200/8). That 20% overhead from start/stop bits matters.

5. Not Accounting for Temperature Drift

Your UART link works perfectly on the bench at 22°C. Then it goes into a product that operates at -20°C to +85°C. The internal RC oscillator drifts 3%, and suddenly you're dropping bytes on cold mornings. Always check oscillator specs over your full operating temperature range.


When To Use Which Baud Rate

Some practical guidelines:

  • 9600 — Default for unknown devices, GPS modules, sensor modules with infrequent data, bootloader fallback. Works with any clock source.
  • 115200 — Standard for development/debugging, moderate data streams, most MCU-to-PC communication. Requires crystal or calibrated HSI.
  • 230400460800 — High-throughput sensor logging, firmware update over UART, FTDI-based tools. Requires crystal and short wires (<30 cm).
  • 9216003000000 — Specialized high-speed applications (ESP32 logging, FTDI at max speed). Requires matched crystals, short traces, good PCB layout. Signal integrity starts to matter.
Above 1 Mbaud, you're pushing UART beyond where it's comfortable. At that point, consider switching to SPI (synchronous, much faster) or USB (differential, noise-immune).

Using the Calculator

The UART Baud Rate & Frame Timing calculator on rftools.io computes everything we've discussed:

  1. Enter your target baud rate9600, 115200, or whatever your peripheral needs.
  2. Set your frame format — data bits (usually 8), stop bits (usually 1), parity (usually none).
  3. Enter your MCU clock frequency — the APB/peripheral clock, not necessarily the core clock. Check your datasheet.
The calculator returns:
  • Bit period — how long each bit is on the wire (useful for scope measurements)
  • Frame period — total time for one character
  • Effective throughput — actual data rate after subtracting UART overhead
  • BRR divisor — the exact register value you need (for 16× oversampling)
  • Actual baud rate — what you really get after integer rounding
  • Baud rate error — green (<0.5%), yellow (0.5–2%), red (>2%)
The error indicator is the most important output. If it's red, your link will have problems. Either change your clock frequency, use a fractional divider (if your MCU supports it), or pick a different baud rate.

Quick Reference: UART Baud Rate Formulas

For anyone who wants the math in one place:

Tbit=1Baud Rate(seconds per bit)T_{bit} = \frac{1}{\text{Baud Rate}} \quad \text{(seconds per bit)}
Frame bits=1+Data+Parity+Stop\text{Frame bits} = 1 + \text{Data} + \text{Parity} + \text{Stop}
Throughput=Baud Rate×Data bitsFrame bits(useful bps)\text{Throughput} = \frac{\text{Baud Rate} \times \text{Data bits}}{\text{Frame bits}} \quad \text{(useful bps)}
BRR=fclk16×Baud Rate(16× oversampling)\text{BRR} = \frac{f_{clk}}{16 \times \text{Baud Rate}} \quad \text{(16× oversampling)}
Error=BactualBtargetBtarget×100%\text{Error} = \frac{|B_{actual} - B_{target}|}{B_{target}} \times 100\%

Keep the error under 2%. Use a crystal when speed matters. Match your baud rates. Your serial links will thank you.

Related Articles