How it works
A UART divides its kernel clock to get the bit rate. The divisor is an integer (or has a small fraction), so the real baud rate is rarely exact:
| Peripheral | Divisor | Real baud |
|---|---|---|
| STM32 USART, ×16 | USARTDIV = round(fck / baud), BRR = USARTDIV | fck / USARTDIV |
| STM32 USART, ×8 | USARTDIV = round(2 fck / baud), BRR[3:0] = USARTDIV[3:0] >> 1 | 2 fck / USARTDIV |
| AVR (ATmega) | UBRR = round(F / (16 baud) − 1), or 8 with U2X | F / (16 (UBRR + 1)) |
| RP2040 / RP2350 (PL011) | IBRD + FBRD/64 = clk / (16 baud) | clk / (16 (IBRD + FBRD/64)) |
| ESP32 | CLKDIV + FRAG/16 = clk / baud | clk / (CLKDIV + FRAG/16) |
fck is the USART kernel clock divided by PRESC on parts that have it (STM32N6, H7, G4, L4+…). STM32 requires USARTDIV ≥ 16.
How much error is OK?
The receiver samples each bit in the middle; over a 10-bit frame the clocks may drift apart by about half a bit, so the sum of both ends’ errors must stay under roughly 4–5 %. The tool marks ±2 % as OK and ±3.5 % as marginal.
The classic example: an Arduino Uno at 16 MHz can’t do 115 200 baud cleanly. Without U2X the error is −3.5 %; with U2X (which the Arduino core enables) it is +2.1 %. It works with most USB-serial adapters, but not with every device.
Presets
Clocks are typical defaults (STM32N6 using HSI 64 MHz as the USART kernel clock, Pico SDK clk_peri, ESP32 APB 80 MHz). Your clock tree may differ: check it in CubeMX or the reference manual and type it in.