ESP32/Wires on the board/29. UART, start to stop
No board required

This one is about the wire, not the chip. Nothing below changes with the board you picked, which is why the chip and language switches are not on it. They come back on the ESP32 pages this one sits underneath.

Wires on the board · 29 of 81

UART, start to stop

A UART has no clock wire. The receiver starts a stopwatch on the first falling edge and reads the middle of each bit at a rate you told it in advance — so getting that rate wrong does not produce an error, it produces a different byte.

/esp32/uart-start-to-stop · any board · 8 min read

Change the receiver's speed. The sender never finds out, and neither does your code.

Sent “H” at 9600, read at 19200
mismatch
grey grid: one bit as the sender counts itsampled 00000001 lsb first
Receiver baud19200
Character sent
Sent
0x48H
Received
0x80 unprintable
0x80 came out of 0x48. The receiver started its timer on the same falling edge and then counted at a faster rate, so each sample lands further from where the bit actually is. Nothing detects this. The port stays open, bytes keep arriving, and every one of them is wrong.

One frame, ten bit times

The line idles high. A falling edge — the start bit — is the receiver's only synchronisation, and everything after it is counted, not measured:

  1. one low start bit,
  2. eight data bits, least significant first,
  3. one high stop bit.

Ten bit times per byte, which is why 9600 baud is 960 characters a second and 115200 is 11,520.

The receiver aims for the middle of each bit — half a bit period after the edge, then one period per bit after that. All the tolerance in the system comes from that half-bit of margin: about 2% of clock error is fine, 5% loses the last bits of the frame first.

Wrong baud is not an error

Nothing in the frame says how fast it was sent. Set the receiver too fast and its ten samples all land inside the start bit; too slow and they drift off the end into the stop bit. Either way it assembles a byte, hands it to your program, and waits for the next one.

Read the garbage — it tells you the ratio. Perfectly readable text with occasional wrong characters means you are close, and it is a clock problem. Solid blocks of the same wrong byte usually means a factor of two. Nothing but 0x00 or 0xFF means you are out by a lot, or looking at the wrong pin.

Two wires, crossed

TX goes to RX and RX goes to TX. There is no address, no master and no negotiation: two devices, one pair, forever. Ground must be common, and if the two boards run at different voltages the 3.3 V side needs level shifting — a 5 V TX into a 3.3 V RX is the standard way to lose a pin.

#define GPS_RX 16   // ESP32 receives here — wire it to the module's TX
#define GPS_TX 17

void setup() {
  Serial.begin(115200);                          // to the computer
  Serial2.begin(9600, SERIAL_8N1, GPS_RX, GPS_TX);   // to the GPS
}

void loop() {
  while (Serial2.available()) Serial.write(Serial2.read());
}

SERIAL_8N1 is the other half of the agreement — eight data bits, no parity, one stop bit — and it is what almost everything uses. The rare device wanting 7E1 or 8N2 will say so in the first paragraph of its datasheet.

Where it wins

A metre of cable, one device, a stream of data that nobody has to request: GPS modules, fingerprint readers, serial LCDs, cellular modems, and one board talking to another. It is the only protocol here that is comfortable off the board, and with an RS-485 transceiver on each end the same frames go a kilometre.

What it cannot do is scale. No addressing means one device per pair of pins, which is exactly the constraint I2C was invented to remove.

The first thing to check

Baud, then wiring, then ground. In that order, because it is the cheapest to test — and because "serial prints garbage" has one dominant cause and it is a number typed into two places that do not match.

Where this goes next

Which UARTs the chip in your hand actually has, and the buffer setting that decides whether a GPS keeps its sentences.

UART and baud rates

Edit this page — content/esp32/uart-start-to-stop.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32 on the forum