Comunicación UART con Arduino, ESP8266 y ESP32: Guía de Pines y Puerto Serie

En este tutorial aprenderás todo lo que necesitas sobre la comunicación UART, desde la arquitectura y la transmisión de datos hasta un ejemplo práctico

En esta guía técnica analizamos en profundidad el protocolo de comunicación serie asíncrono UART (Universal Asynchronous Receiver-Transmitter), su temporización a nivel físico y cómo depurar tramas con osciloscopio en proyectos de electrónica:

  • Asignación de puertos serie y pines: líneas TX y RX en Arduino Uno, Nano, Mega 2560, ESP8266 y ESP32.
  • Estructura de la trama serie 8N1: función del bit de START, 8 bits de datos (LSB first), bit de paridad opcional y bits de STOP.
  • Reglas de diseño y seguridad eléctrica: adaptación de niveles entre 5 V y 3,3 V, masa común obligatoria y resolución del conflicto de subida con el puerto USB.
  • Diagnóstico con osciloscopio: medición experimental del tiempo de bit (tasa de baudios real), análisis de fluctuación (jitter) y decodificación serie de caracteres ASCII en pantalla.
UART en miniatura

Comparación de protocolos de comunicación de microcontroladores desde una perspectiva UART

UART es el único protocolo de comunicación en serie asíncrono y se utiliza en módulos lectores de tarjetas RFID como interfaz de comunicación independiente. Pero UART generalmente se encuentra más dentro de microcontroladores.

En comparación con I2C y SPI, UART es el protocolo de comunicación más antiguo, inventado en 1960 por Gordon Bell en Digital Equipment Corporation.
La siguiente tabla compara los protocolos de comunicación I2C, SPI y UART según diferentes categorías.

. . . . . . . . . .

 DescripciónI2CSPIUART
Inventado por1982 por Philips Semiconductor1970 por Motorola1960 por Gordon Bell en Digital Equipment Corporation
Transferencia de datos síncronaSe necesita una línea de reloj para sincronizar la comunicaciónVerdaderoVerdaderoFalso
Transferencia de datos asíncronaEn lugar de una señal de reloj, el propio flujo continuo de datos (data stream) contiene señales de inicio y de paradaFalseFalseTrue
Rendimiento10 kbps a 1 Mbps (hasta 3,4 Mbps en High-Speed)Hasta 10 Mbps o más (según el reloj del microcontrolador)Típico 9.600 a 115.200 baudios (máx. ~1-2 Mbps)
El esclavo necesita una dirección únicaVerdaderoFalsoFalso
Número de pines necesarios242
Protocolo de comprobación de erroresVerdaderoFalsoVerdadero
Multi-maestroPuede tener varios maestros que controlen uno o varios esclavosVerdaderoFalsoFalso
Multi-esclavoPuede conectar varias salves a un solo maestroVerdaderoVerdaderoFalso
Conmutación de paquetesLos datos transferidos se agrupan en paquetes/mensajes, compuestos por una cabecera y una carga útilVerdaderoFalsoFalso
Single-endedLos datos se transfieren por un solo cableTrue
Datos en serie (SDA)
Falso
Master in Slave Out (MISO)
Master Out Slave In (MOSI)
False
Conexión serieLos datos se transfieren bit a bit a lo largo de un solo cableVerdaderoVerdaderoVerdadero

La principal desventaja de UART es que no se admite la comunicación multimaestro y multiesclavo. Por lo tanto, siempre hay 1 dispositivo maestro y 1 dispositivo esclavo.

Dado que la transferencia de datos es asincrónica, UART no necesita una señal de reloj para sincronizar la transferencia de datos, y los datos se pueden enviar y recibir en diferentes momentos. Si los dispositivos maestro y esclavo envían y reciben datos al mismo tiempo, lo que se denomina comunicación dúplex completo, cada dispositivo necesita 2 registros de desplazamiento para almacenar los caracteres de transmisión y recepción. Esto es necesario porque un dispositivo puede recibir un nuevo byte de datos mientras envía un byte de datos.
En comparación, en la comunicación SPI, el maestro y el esclavo solo necesitan un registro de desplazamiento para recibir señales porque, debido a la transferencia de datos sincrónica, el registro de desplazamiento se vacía y se llena al mismo tiempo y debido a que el tamaño del registro de desplazamiento es el mismo para todos los dispositivos, el la transferencia de datos comienza y termina al mismo tiempo.

Además de la comunicación full duplex, existen otras dos formas de comunicación que solo requieren un registro de desplazamiento único (shift register):

  • simplex: una dirección sin provisión para el dispositivo receptor (unidireccional (simplex))
  • semidúplex: semidúplex (half-duplex): los dispositivos transmiten y reciben alternativamente

Configuración del protocolo de comunicación UART

En la mayoría de las aplicaciones, el bit menos significativo se transmite primero. Para evitar la pérdida de datos a altas velocidades de transmisión, muchos dispositivos UART tienen un pequeño búfer FIFO (primero en entrar, primero en salir) entre el registro de desplazamiento y el sistema host.

La frecuencia del reloj suele ser de 8 a 16 veces la tasa de bits. El receptor prueba el estado de la señal entrante con la frecuencia del reloj. Si el bit de inicio excede al menos la mitad del tiempo del bit, el receptor detecta el bit de inicio válido. De lo contrario, se ignora el bit de inicio. La velocidad del reloj, también conocida como velocidad en baudios, generalmente se establece en 9600 bits por segundo.

Transmisión de datos y encuadre UART

Reglas de seguridad y diseño eléctrico en comunicación UART
  • Incompatibilidad de tensiones 5 V vs. 3,3 V: La línea TX de una placa Arduino Uno o Mega emite niveles TTL de 5 V constantes. Si conectas este pin directamente al pin RX de un ESP8266 o ESP32, sobrepasarás la tensión máxima admisible de sus compuertas destruyendo el microcontrolador. Intercala siempre un divisor de tensión (1 kΩ en serie y 2 kΩ a masa) o un convertidor de nivel lógico bidireccional MOSFET. La línea TX del ESP32 (3,3 V) puede conectarse directamente al RX del Arduino Uno porque supera el umbral de entrada alta (VIH ≥ 3,0 V).
  • Conflicto de programación USB en pines D0 (RX) y D1 (TX): En Arduino Uno y Nano, los pines 0 y 1 están conectados en paralelo con el chip conversor USB-Serie de la placa. Si mantienes conectados módulos o cables en RX durante la subida de un programa, el bootloader fallará con errores de sincronismo (stk500_recv()). Desconecta siempre el pin RX antes de pulsar «Subir» en el IDE.
  • Masa común indispensable (GND): La comunicación UART es asíncrona y no balanceada: cada nivel de tensión se mide respecto a tierra. Si las placas no tienen sus pines GND estrictamente unidos con un cable sólido, las referencias de tensión flotarán provocando errores de encuadre (Framing Errors) o caracteres corruptos aleatorios.
Transmisión y encuadre de datos UART

Una ventaja de UART es que solo se necesitan 2 cables para la comunicación entre el dispositivo maestro y esclavo, ya que no hay necesidad de una línea de reloj y, al igual que la comunicación SPI, ya no hay una línea de selección esclava. Las 2 líneas son:

  • TX (transmisión)
  • RX (recepción)

En la imagen de arriba, ves que las líneas están cruzadas para que TX y RX estén conectados entre los dispositivos.

Primero, el dispositivo que transmite los datos recibe la trama de datos en paralelo desde el bus de datos. El dispositivo UART agrega el bit de inicio, el bit de paridad y los bits de parada a la trama de datos antes de que el paquete de datos completo se envíe a través de UART al dispositivo receptor. El dispositivo UART receptor extrae la trama de datos y la transmite en paralelo a través del bus de datos.

La siguiente imagen y descripción brindan una explicación más detallada de los procesos de encuadre durante la comunicación UART.

Encuadre de datos UART

Si no hay comunicación UART activa, el estado inactivo en las líneas de comunicación es lógico ALTO porque en el momento de la telegrafía, una línea preparada alta indica que el transmisor no está dañado.

El bit de inicio es el primer bit que se transfiere como lógica BAJA, indica que se transfiere un nuevo carácter.

Después, el bit de inicio sigue la trama de datos real, cuyo formato y tamaño de los datos se pueden configurar entre 5 y 9 bits.

Después de que la trama de datos sigue un bit de paridad opcional que le da a UART la capacidad de verificar errores. El bit de paridad es 0 si la suma de 1 bits en la trama de datos es par y 1 si la suma de 1 bits en la trama de datos es impar. Este método de verificación de errores evita que los bits cambien durante la transferencia.

Los últimos bits se reservan como bits de parada e indican que el carácter está completo. Por lo tanto, los bits de parada tiran de la línea ALTA

Si la comunicación se termina y debe terminarse, el maestro ha puesto la línea en lógica BAJA por más de un tiempo de carácter. Esto le indica al esclavo que la comunicación UART está completa.

Ventajas y desventajas de UART

Ventajas

  • UART solo usa 2 cables para la comunicación
  • No se necesita una línea de señal de reloj adicional
  • La comprobación de errores es posible gracias al bit de paridad

Desventajas

  • El tamaño de la trama de datos está limitado a 9 bits.
  • No hay soporte para la comunicación con múltiples maestros o esclavos.

Comunicación UART entre Arduino y ESP8266

Pines UART y Puertos Serie en Arduino Uno, Nano, Mega, ESP8266 y ESP32

Cada microcontrolador dispone de una arquitectura serie diferente. Para conectar módulos GPS, módems GSM, lectores Bluetooth o comunicar dos placas entre sí, es fundamental conocer qué pines corresponden a los puertos serie físicos (Hardware Serial):

Microcontrolador Puerto Serie Pin TX (Transmisión) Pin RX (Recepción) Tensión Lógica Características y Conexión
Arduino Uno / Nano Serial (Único) D1 (TX) D0 (RX) 5 V Compartido con el chip USB-Serial. Desconectar cables al programar.
Arduino Mega 2560 Serial a Serial3 1 (TX0), 18 (TX1), 16 (TX2), 14 (TX3) 0 (RX0), 19 (RX1), 17 (RX2), 15 (RX3) 5 V 4 puertos UART independientes por hardware sin sobrecarga de CPU.
ESP8266 (NodeMCU / D1) Serial / Serial1 TX0 (GPIO 1), TX1 (GPIO 2) RX0 (GPIO 3), Sin RX en Serial1 3,3 V (No tolera 5 V) UART0 para consola/cargas; UART1 solo permite depuración de salida.
ESP32 (WROOM-32) Serial a Serial2 GPIO 1 (TX0), GPIO 10 (TX1), GPIO 17 (TX2) GPIO 3 (RX0), GPIO 9 (RX1), GPIO 16 (RX2) 3,3 V (No tolera 5 V) 3 puertos UART completos remapeables a cualquier GPIO mediante matriz interna.

En el siguiente ejemplo, queremos enviar una cadena desde un Arduino Uno a un ESP8266 NodeMCU a través de la línea de comunicación UART y mostrar la cadena en una pantalla LCD.

La siguiente imagen muestra la conexión entre el microcontrolador Arduino y ESP8266 y la pantalla LCD. Si no sabe qué son los pines TX (transmisión) y RX (recepción), encontrará una descripción general muy útil en los artículos de asignación de pines del microcontrolador: Arduino Nano, Arduino Uno, Arduino Mega, ESP8266. O mejor si descarga el libro electrónico de la hoja de datos del microcontrolador.

Haga clic en la imagen para ampliarla y ver mejor qué pines se utilizan.

Comunicación UART Arduino y ESP8266

En la siguiente parte, vamos paso a paso por el código del programa.

La primera parte es el script Arduino Uno que envía una cadena a través de UART.

void setup() {
  Serial.begin(9600); // Inicializa UART a 9600 baudios (8N1)
}

void loop() {
  Serial.println("OK"); // Envía trama serie terminada en retorno de carro y salto de línea (
)
  delay(1000);
}

El guión es muy breve y sencillo. No se incluyen bibliotecas. En la función de configuración, necesitamos establecer la velocidad en baudios en 9600. Un segundo argumento opcional configura los datos, la paridad y los bits de parada. El valor predeterminado es 8 bits de datos, sin paridad y un bit de parada que estamos usando en este ejemplo.

En la función de bucle, enviamos la cadena a través de la función en serie cada segundo. La parte » r» le dirá al receptor que la cadena está completa.

Ahora nos ocupamos del script del receptor para el ESP8266 NodeMCU.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); 
char buff[50];
volatile byte indx = 0;

void setup() {
  Serial.begin(9600); // Misma velocidad en baudios que el emisor
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Esperando UART...");
}

void loop() {
  if (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '
' || c == '
') {
      if (indx > 0) {
        buff[indx] = ''; // Fin de cadena
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Recibido UART:");
        lcd.setCursor(0, 1);
        lcd.print(buff);
        indx = 0;
      }
    } else if (indx < sizeof(buff) - 1) {
      buff[indx++] = c;
    }
  }
}

Primero necesitamos incluir la biblioteca LiquidCrystal_I2C para facilitar la comunicación con la pantalla LCD. Se debe incluir el segundo cable de la biblioteca para permitir la comunicación I2C entre el NodeMCU y la pantalla LCD.
Inicializamos la pantalla LCD de 20 × 4 a la dirección HEX 0x27. Para identificar la dirección hexadecimal de su dispositivo I2C, encontrará un escáner de direcciones hexadecimales en este artículo.
Las variables buff almacenan los valores entrantes a través de UART y la variable indx almacena el índice de 8 bits.

En la función de configuración, la velocidad en baudios también se establece en 9600, que debería coincidir con la velocidad en baudios del Arduino Uno. La pantalla LCD también se inicializa, limpia y la luz de fondo está encendida.

En la función de bucle, verificamos si la conexión en serie está disponible y luego leemos los datos en serie entrantes byte por byte mientras escribimos cada byte en el búfer de matriz de bytes. Si detectamos el final de la cadena, definido por » r», imprimimos el contenido de la tabla en la pantalla LCD. Después de 1 segundo, restablecemos el índice de la matriz y limpiamos la pantalla para los siguientes datos entrantes.

UART en miniatura

Conclusión

En este tutorial, primero comparamos el protocolo de comunicación UART con I2C y SPI. También discutimos la configuración de UART y cómo se transmiten los datos entre 2 dispositivos. Al final de este artículo, vimos un ejemplo para transferir una cadena de un Arduino Uno a un NodeMCU a través de UART.

Si tiene alguna pregunta sobre la comunicación UART, utilice la sección de comentarios a continuación para hacer sus preguntas. Les responderé lo antes posible.

Diagnóstico de la Señal UART con Osciloscopio: Baudios, Jitter y Tramas Serie

Al no contar con una línea de reloj externa que sincronice los datos, la comunicación UART depende exclusivamente de que el emisor y el receptor tengan relojes internos con una frecuencia casi idéntica. Cuando recibes caracteres extraños, símbolos sin sentido o bloqueos en el búfer de entrada, el osciloscopio digital es la herramienta fundamental para analizar la integridad temporal de la señal.

1. Identificación visual de la trama 8N1 en pantalla

Al conectar la sonda del osciloscopio a la línea TX (con pinza de cocodrilo a GND), la señal de reposo se mantiene en nivel ALTO (Mark / +5 V o +3,3 V). Una trama estándar 8N1 se compone de:

  • Bit de START: Transición obligatoria de nivel ALTO a BAJO durante exactamente un período de bit (Tb). Este flanco de bajada inicial sincroniza el temporizador de muestreo del receptor.
  • 8 bits de datos: Se transmiten comenzando por el bit menos significativo (LSB first). Los niveles de tensión corresponden a ‘0’ (BAJO) y ‘1’ (ALTO).
  • Bit de paridad (opcional): Bit adicional para detección de errores simples de bit.
  • Bit de STOP: Retorno obligatorio a nivel ALTO durante mínimo 1 o 2 períodos de bit (Tb) antes de la siguiente trama o período de reposo.

2. Medición experimental de la velocidad en baudios real

Para comprobar si la velocidad en baudios real coincide con la programada, mide con los cursores de tiempo del osciloscopio la anchura mínima de un pulso individual (el tiempo de bit Tb):

  • Fórmula de cálculo: Baud Rate = 1 / Tb.
  • Para 9.600 baudios, el ancho de bit exacto es Tb = 104,17 μs.
  • Para 115.200 baudios, el ancho de bit exacto es Tb = 8,68 μs.
  • Tolerancia admisible: El receptor muestrea los datos en el centro aproximado de cada bit (al 50% de Tb). Si la discrepancia de frecuencia entre los osciladores supera el 2,5% - 3%, el error temporal acumulado al llegar al 8.º bit de datos o al bit de parada provocará un error de encuadre (Framing Error) y la corrupción sistemática del mensaje.

3. Configuración del disparo (Trigger) para tramas serie

  • Trigger por flanco: Selecciona Flanco de bajada (Falling Edge) en el canal conectado a la línea serie con acoplamiento DC. Ajusta el nivel de disparo a la mitad de la amplitud (1,65 V para sistemas de 3,3 V o 2,5 V para 5 V).
  • Modo de disparo: Utiliza el modo Normal o Single para capturar ráfagas intermitentes de texto sin que se sobreescriba la pantalla en los períodos de reposo.
  • Base de tiempos: Para 9.600 baudios (una trama completa de 10 bits dura aproximadamente 1,04 ms), ajusta la escala horizontal a 200 μs/div o 500 μs/div.

4. Decodificación de caracteres serie por hardware

Los osciloscopios digitales con decodificador serie integrado analizan en tiempo real la forma de onda analógica y muestran directamente sobre la pantalla los caracteres en formato ASCII o hexadecimal, facilitando la depuración inmediata de protocolos propietarios:

Modelo Ancho de Banda Canales Tasa de Muestreo Memoria Decodificación UART / RS232
Rigol DS1054Z 50 MHz (ampliable a 100 MHz) 4 analógicos 1 GSa/s 24 Mpts UART, RS232, I2C, SPI (Trigger y Decode integrado)
Siglent SDS1104X-E 100 MHz 4 analógicos 1 GSa/s 14 Mpts UART, RS232, I2C, SPI, CAN, LIN por hardware
Hantek DSO2D10 100 MHz 2 analógicos + AWG 1 GSa/s 8 Mpts Decodificación UART y buses serie en pantalla
FNIRSI 1014D 100 MHz (efectivo ~30 MHz) 2 analógicos + AWG 1 GSa/s (compartido) 240 Kpts Sin decodificación serie (solo análisis analógico)

Para inspeccionar puertos UART y depurar comunicaciones serie en proyectos con microcontroladores, el Rigol DS1054Z destaca por su memoria profunda de 24 Mpts, que permite registrar cientos de tramas consecutivas sin perder resolución de muestreo:

Preguntas frecuentes sobre comunicación serie UART

¿Hasta qué velocidad en baudios es fiable la librería SoftwareSerial en Arduino Uno?

Dado que SoftwareSerial emula el protocolo serie mediante interrupciones por software sin hardware dedicado, funciona con total estabilidad a 9.600 y 19.200 baudios (y hasta 38.400 baudios en tramas cortas), pero a 115.200 baudios pierde bits de forma continua debido a la latencia de las interrupciones del microcontrolador ATmega328P. Si tu periférico requiere 115.200 baudios, utiliza un puerto serie por hardware nativo (como Serial1/2/3 en Arduino Mega o ESP32).

¿Por qué aparecen caracteres extraños o símbolos raros en el Monitor Serie?

La causa principal es una discrepancia en la velocidad de transmisión (baud rate). Si en tu código configuras Serial.begin(115200) pero el Monitor Serie está ajustado a 9600 baudios (o viceversa), el receptor interpretará los anchos de bit de forma errónea, mostrando caracteres basura. Otra causa común es la falta de una conexión de masa compartida (GND) entre las dos placas, lo que hace que los niveles lógicos floten aleatoriamente.

¿Por qué falla la subida del sketch al Arduino cuando tengo cables conectados en los pines 0 (RX) y 1 (TX)?

En las placas Arduino Uno y Nano, los pines digitales 0 y 1 están conectados internamente a las líneas de datos del integrado de interfaz USB (ATmega16U2 o CH340). Al conectar un sensor o microcontrolador externo a estos mismos pines, se produce un conflicto eléctrico en la línea que bloquea las órdenes de programación del bootloader. Desconecta siempre los cables de RX y TX antes de cargar un nuevo sketch.

1 comentario en «Comunicación UART con Arduino, ESP8266 y ESP32: Guía de Pines y Puerto Serie»

  1. Arduino y Esp8266 trabajan a distinta tensión, Arduino trabaja con niveles TTL (5v) y Esp trabaja a 3,3v. Y has conectado directamente el puerto serie de un dispositivo al otro dispositivo sin ningún adaptador de niveles (Level Shifter) ¿No se puede romper el puerto serie del ESP?

    Responder

Deja un comentario