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 InterfaceTX PinRX PinNotes
UART0GPIO1 (TXD0)GPIO3 (RXD0)Connected to USB-Serial. Used for programming and Serial monitor. Avoid using for other purposes.
UART1GPIO10GPIO9⚠️ These pins are connected to the SPI flash memory on ESP32-WROOM modules. Not usable on most dev boards.
UART2GPIO17 (TX2)GPIO16 (RX2)✅ Fully usable. Default choice for external serial devices.
💡 Key Insight UART1's default pins (GPIO9, GPIO10) are used by the internal SPI flash on most ESP32 modules. You can still use UART1 by remapping it to different GPIOs in software — a common practice among ESP32 developers.

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:

ParameterOptions
Baud rate300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
Data bits5, 6, 7, 8 (default)
ParitySERIAL_8N1 (none), SERIAL_8E1 (even), SERIAL_8O1 (odd)
Stop bits1 (default), 2
Flow controlRTS/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

Related Guides