ESP32 UART Pins: Complete Serial Communication Guide
The ESP32 has 3 UART interfaces: UART0, UART1, and UART2. UART0 is typically connected to the USB-Serial converter for programming and debugging, while UART1 and UART2 are available for communicating with external serial devices like GPS modules, Bluetooth modules, and serial displays.
One of the ESP32's strengths is that UART pins can be remapped to almost any GPIO using the IO MUX, giving you flexibility in PCB design.
Default ESP32 UART Pin Assignments
| UART Interface | TX Pin | RX Pin | Notes |
|---|---|---|---|
| UART0 | GPIO1 (TXD0) | GPIO3 (RXD0) | Connected to USB-Serial. Used for programming and Serial monitor. Avoid using for other purposes. |
| UART1 | GPIO10 | GPIO9 | ⚠️ These pins are connected to the SPI flash memory on ESP32-WROOM modules. Not usable on most dev boards. |
| UART2 | GPIO17 (TX2) | GPIO16 (RX2) | ✅ Fully usable. Default choice for external serial devices. |
Arduino Code: Using UART2
Here's how to communicate with a serial device (e.g., GPS module) using UART2:
// ESP32 UART2 Example - Serial Communication
#include <HardwareSerial.h>
HardwareSerial Serial2(2); // Use UART2
void setup() {
Serial.begin(115200); // USB Serial for debugging
Serial2.begin(9600, SERIAL_8N1, 16, 17); // RX=GPIO16, TX=GPIO17
Serial.println("ESP32 UART2 Ready!");
}
void loop() {
if (Serial2.available()) {
String data = Serial2.readString();
Serial.print("Received: ");
Serial.println(data);
}
if (Serial.available()) {
String cmd = Serial.readString();
Serial2.print(cmd);
}
}
Remapping UART to Any GPIO
The ESP32 IO MUX allows you to assign UART TX/RX to almost any pin. Here's an example using UART1 on custom pins:
// ESP32 UART1 Remapped to Custom Pins
#include <HardwareSerial.h>
HardwareSerial Serial1(1); // Use UART1
// Define custom pins for UART1
#define UART1_TX 4
#define UART1_RX 5
void setup() {
Serial.begin(115200);
Serial1.begin(115200, SERIAL_8N1, UART1_RX, UART1_TX);
Serial.println("UART1 is now on GPIO4 (TX) and GPIO5 (RX)");
}
void loop() {
Serial1.println("Hello from UART1!");
delay(2000);
}
UART Baud Rate and Configuration Options
The ESP32 serial configuration supports all standard baud rates and framing options:
| Parameter | Options |
|---|---|
| Baud rate | 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 |
| Data bits | 5, 6, 7, 8 (default) |
| Parity | SERIAL_8N1 (none), SERIAL_8E1 (even), SERIAL_8O1 (odd) |
| Stop bits | 1 (default), 2 |
| Flow control | RTS/CTS supported via hardware |
UART with Hardware Flow Control (RTS/CTS)
ESP32 UART supports hardware flow control for reliable high-speed communication:
// UART2 with hardware flow control
#include <HardwareSerial.h>
HardwareSerial Serial2(2);
void setup() {
// RX=16, TX=17, RTS=18, CTS=19
Serial2.begin(115200, SERIAL_8N1, 16, 17, false, 18, 19);
}
Best Practices for ESP32 Serial Communication
- Use UART2 for external serial devices — it has no conflicts with flash or USB-Serial
- Avoid UART0 GPIO1/GPIO3 for anything other than programming/debugging
- Remap UART1 if you need a third serial port — assign it to GPIO4, GPIO5, or other safe pins
- Match voltage levels: ESP32 UART is 3.3V. Use a level shifter for 5V serial devices
- Add pull-up resistors on RX lines in noisy environments
🔧 Explore UART Pins Interactively
Use our interactive pinout tool to see UART assignments and check for conflicts with other peripherals.
Open Interactive Pinout