I have a project that needs 3 serial ports on my ESP32 Dev 38-pin MCU. Two of them are for Nextion touch displays and the other is for a GPS.

The problem from what I understand is that the ESP32 has 3 hardware serial ports, of which only 2 can be used. GPIO 1 and 3 can not be connected to the display during upload and the software serial that is in Arduino IDE 2.0.4 is not compatible with an ESP32.

Can anyone tell me how I can use 3 serial ports?


  • use ota to upload sketches, it's faster, safer, and more flexible anyway. you can also use a software serial, mos def.
    – dandavis
    Commented Mar 8, 2023 at 6:18
  • It's easy to remap any of the ESP32 serial port pins to other pins, so you're not bound to the standard pinout.
    – StarCat
    Commented Mar 8, 2023 at 10:48
  • Welcome Richard, your question is interesting and a common problem in the Arduino arena. I simply use a SPI or I2C board that outputs RS232. I stumbled across them a few years back and used several, they worked great. I do not remember what they were called but here is a link to one of the many that are available: "andino.systems/extensions/rs232"This was the first search term I used: arduino SPI to RS232 module". Here is another link for the Pi: "forums.raspberrypi.com//…"
    – Gil
    Commented Mar 9, 2023 at 3:32
  • Not a full answer, but, depending on your GPS model, you might be able to use I2C instead.
    – dda
    Commented Jan 19 at 14:21

2 Answers 2


Yes it is possible to assign any GPIO pins to serial using HardwareSerial library for up to 3 UART Connections. See this link for reference: https://copperhilltech.com/blog/esp32-programming-three-serial-ports-uarts-using-the-arduino-ide/

I'm playing with 2 nextions and esp32 also. would be great to chat with you and brainstorm

    #define UART1_ODU_BAUD_RATE 2400
    #define U1RXD 32
    #define U1TXD 33

Use this for UART Init in the setup

    // UART1 Configuration
      uart_config_t Configurazione_UART1 = {
        .baud_rate = UART1_ODU_BAUD_RATE,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_EVEN,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
      uart_param_config(NUMERO_PORTA_SERIALE, &Configurazione_UART1);
      esp_log_level_set(TAG, ESP_LOG_INFO);
      uart_driver_install(NUMERO_PORTA_SERIALE, BUF_SIZE, BUF_SIZE, 20, &uart1_queue, 0);
      xTaskCreate(UART_ISR_ROUTINE, "UART_ISR_ROUTINE", 2048, NULL, 12, NULL);

Create a ISR function

    static void UART_ISR_ROUTINE(void *pvParameters)                //uart1
      uart_event_t event;
      size_t buffered_size;
      bool exit_condition = false;
      String ODU_PAC_ONE_Temp = "";
      ODU_PAC_ONE = "";
      while (1) {
        if (xQueueReceive(uart1_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
          if (event.type == UART_DATA) {
            uint8_t UART1_data[128];
            int UART1_data_length = 0;
            ESP_ERROR_CHECK(uart_get_buffered_data_len(UART_NUM_1, (size_t*)&UART1_data_length));
            UART1_data_length = uart_read_bytes(UART_NUM_1, UART1_data, UART1_data_length, 100);
            for (byte i = 0; i < UART1_data_length; i++) {
                ODU_PAC_ONE_Temp += (int) UART1_data[i];
          else if (event.type == UART_FRAME_ERR) {
        if (exit_condition) {

You will get your data in here (int) UART1_data[i]

  • 1
    This answer might benefit from a bit of explanation. In what way is this better than a simple port remap?
    – StarCat
    Commented Dec 20, 2023 at 13:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.