Asesoría Agenda una llamada de descubrimiento técnico hoy mismo »

· Industrial Protocols  · 12 min de lectura

Modbus RTU y TCP: La Guía Definitiva (Protocolo, Endianness y MBAP)

Más allá del cable. Aprende a dominar el Byte Swapping, los Function Codes y la estructura real de los mensajes Modbus para integraciones 100% fiables.

Más allá del cable. Aprende a dominar el Byte Swapping, los Function Codes y la estructura real de los mensajes Modbus para integraciones 100% fiables.

Modbus RTU y TCP: una PDU, dos envolturas de transporte

Modbus es más fácil de diagnosticar al separar aplicación y transporte. RTU y TCP pueden solicitar los mismos registros de retención, pero delimitan tramas, correlacionan respuestas y exponen fallos distintos. Esta guía cubre modelo de datos, PDU, trama RTU y CRC, temporización serie, cabecera MBAP de TCP, pasarelas y despliegue. No prescribe cableado ni terminación RS-485; consulte la Guía de supervivencia Modbus RTU. Tampoco sustituye códigos de función y escrituras controladas de Códigos de función Modbus. [M-A-P-001]

Alcance, evidencia y límite de seguridad

Los ejemplos de bytes son simulaciones locales, no evidencia de acceso a un PLC, pasarela, adaptador serie ni proceso de producción. Se ejecutaron el 2026-07-21 con CPython 3.12.3 y solo la biblioteca estándar de Python. No se usaron sockets, puertos serie, credenciales, dispositivos ni clientes Modbus de terceros. Los recibos prueban construcción y rechazo de tramas, no interoperabilidad ni compatibilidad con un mapa de fabricante. Todo resultado dependiente de hardware es BENCH-ONLY—NOT VALIDATED HERE.

Modbus RTU y Modbus TCP no proporcionan autenticación ni autorización. No exponga un controlador, pasarela o conversor serie a una red no confiable. Segmente el tráfico OT, use acceso remoto aprobado y restrinja el puerto 502 y la administración serie. No descubra producción mediante escaneos amplios o escrituras de prueba. Toda escritura autorizada requiere procedimiento del responsable del activo, mantenimiento, valor de reversión conocido, lectura independiente y personal cualificado. Antes del trabajo físico, desenergice tableros y siga instrucciones del fabricante, LOTO y EPP. Este artículo no ofrece garantías de disponibilidad, latencia, cumplimiento normativo ni fiabilidad. [M-A-P-001]

El modelo de datos no es la dirección en la trama

El protocolo de aplicación Modbus define cuatro clases lógicas de objetos. Las bobinas y las entradas discretas son objetos de un bit; los registros de entrada y los registros de retención son palabras de 16 bits. Las bobinas y los registros de retención pueden ser escribibles cuando el servidor implementa la función pertinente; las entradas discretas y los registros de entrada son de solo lectura dentro del modelo. Los prefijos de referencia 0x, 1x, 3x y 4x conocidos en manuales son convenciones de documentación. No son campos transmitidos en una solicitud. [M-A-P-001]

Clase de objetoNotación de referencia habitualDatos en la tramaAcceso habitual
Bobinas0xxxxbits empaquetadoslectura/escritura
Entradas discretas1xxxxbits empaquetadoslectura
Registros de entrada3xxxxpalabras de 16 bitslectura
Registros de retención4xxxxpalabras de 16 bitslectura/escritura

Una PDU de solicitud lleva un código de función y campos como dirección inicial basada en cero y cantidad. Un manual que etiqueta un valor como 40101 puede querer decir el desplazamiento 100, mientras un SCADA puede pedir 40101 o 101. Son convenciones de interfaz, no una conversión universal. Confirme mapa, convención de la API cliente y un vector de lectura aprobado antes de poner en servicio. Una respuesta correcta no prueba escala, signo, unidad de ingeniería ni orden de bytes o palabras. [M-A-P-001]

La especificación de aplicación emplea cliente y servidor: el cliente inicia la transacción y el servidor ejecuta la acción o responde. La guía histórica de línea serie también usa maestro y esclavo para esa relación. En integraciones nuevas documente cliente/servidor: la terminología heredada no define identidad de red ni permisos de seguridad. El papel protocolar no reemplaza la autorización operativa.

ADU y PDU: una separación útil

La unidad de datos de protocolo (PDU) es la parte común de aplicación: un byte de código de función más datos. Una PDU para leer registros de retención desde el desplazamiento 100, cantidad 2, es 03 00 64 00 02. La unidad de datos de aplicación (ADU) envuelve esa PDU para un transporte concreto. Mantener explícita la separación evita un error frecuente de diagnóstico: tratar la cabecera TCP o la dirección y el CRC de RTU como parámetros del código de función.

En RTU, la ADU es:

dirección de unidad | código de función + datos (PDU) | byte bajo de CRC | byte alto de CRC

En TCP, la ADU es:

cabecera MBAP (7 bytes) | código de función + datos (PDU)

La misma PDU puede aparecer, por tanto, dentro de cualquiera de las dos envolturas. Una pasarela suele retirar la cabecera MBAP de TCP, usar el identificador de unidad para seleccionar un destino serie según su configuración, enviar una ADU RTU aguas abajo y construir después una respuesta TCP aguas arriba. La traducción deja de ser transparente si fallan el tiempo de espera, la cola, el mapeo de unidades o los parámetros serie. [M-A-P-002] [M-A-P-003]

Trama RTU, temporización y CRC

RTU coloca una dirección de servidor de un byte antes de la PDU y agrega un CRC de dos bytes calculado sobre dirección y PDU. El CRC se transmite primero por el byte de menor orden. Detecta muchas tramas corruptas, pero no es un mecanismo de seguridad: un emisor defectuoso o un atacante puede construir un CRC válido para contenido no deseado. Valídelo antes de interpretar una PDU, conserve la captura original si falla y no “repare” bytes dentro de un registro de diagnóstico. [M-A-P-003]

El delimitado RTU depende también del silencio. La guía de línea serie define un intervalo entre tramas de al menos 3,5 tiempos de carácter; una pausa interior superior a 1,5 tiempos de carácter hace que el receptor considere incompleta la trama. Por encima de 19.200 bit/s, la guía recomienda valores fijos de 750 microsegundos para el tiempo entre caracteres y 1,75 milisegundos para el retardo entre tramas. Registre velocidad, paridad, bits de datos, bits de parada, configuración de tiempos y ambas ADU sin procesar. Una captura que empieza a mitad de mensaje no puede reconstruirse con seguridad buscando un código de función reconocible. [M-A-P-003]

La fixture P-RTU-01 es una solicitud de lectura de registros de retención a la unidad 1: 01 03 00 00 00 0A C5 CD. Los seis primeros bytes solicitan diez registros desde el desplazamiento cero. Aplicar el algoritmo CRC estándar de Modbus a 01 03 00 00 00 0A produce el CRC numérico 0xCDC5; RTU transmite ese valor como C5 CD porque el byte bajo se envía primero. La fixture es deliberadamente local: comprueba orden y aritmética, no un enlace serie. [M-A-P-003]

Trama TCP y cabecera MBAP

Modbus TCP sustituye la dirección y el CRC de RTU por la cabecera MBAP (Modbus Application Protocol) de siete bytes: dos bytes de identificador de transacción, dos de identificador de protocolo, dos de longitud y un identificador de unidad. La PDU sigue inmediatamente. El identificador de protocolo es cero para Modbus. La longitud cuenta el identificador de unidad más la PDU; no cuenta los seis primeros bytes MBAP. [M-A-P-002]

Campo MBAPTamañoUso de validación
Identificador de transacción2 bytesAsociar una respuesta con una solicitud pendiente.
Identificador de protocolo2 bytesDebe ser 0x0000 para Modbus.
Longitud2 bytesDebe equivaler a los bytes desde el identificador de unidad hasta la PDU.
Identificador de unidad1 byteIdentifica una unidad aguas abajo en muchas pasarelas; en un servidor directo depende del equipo.

La fixture P-TCP-01 es 00 01 00 00 00 06 11 03 00 64 00 02. Declara transacción 1, protocolo 0, longitud 6, identificador de unidad 17, función 3, desplazamiento 100 y cantidad 2. La longitud es seis porque cubre 11 03 00 64 00 02. Antes de decodificar datos, una respuesta debe correlacionarse con la solicitud vigente; si un cliente tiene varias transacciones pendientes, no basta con hacer coincidir función y unidad. [M-A-P-002]

El comportamiento de flujo de TCP marca otro límite. Una sola llamada a recv() no garantiza recibir una ADU completa, y una lectura puede contener más de una. Acumule bytes hasta que la longitud MBAP produzca una ADU completa, rechace longitudes imposibles bajo un límite definido por la aplicación y conserve los bytes restantes para el mensaje siguiente. Los mecanismos de integridad de TCP no sustituyen la validación MBAP, de transacción, función, recuento de bytes ni semántica. Un socket conectado solo indica que el par TCP aceptó una conexión.

Identificadores de unidad y dominios de fallo de pasarela

El identificador de unidad es sencillo solo cuando la documentación del destino explica su significado. En una pasarela TCP-serie suele seleccionar la unidad serie aguas abajo. En un servidor TCP directo puede ignorarse, fijarse o utilizarse para enrutamiento específico del fabricante. No suponga que 0, 1 o 255 tienen un significado universal. Registre modelo exacto de pasarela, revisión de firmware, configuración de mapeo y documentación del destino junto con el recibo de puesta en servicio. [M-A-P-002]

Una pasarela crea dominios de fallo aguas arriba y aguas abajo. El cliente puede completar TCP mientras el puerto serie tiene paridad incorrecta, unidad indisponible, espera agotada o un problema eléctrico. A la inversa, una respuesta RTU válida puede retrasarse, traducirse a excepción o perderse por una política aguas arriba. Diagnostique desde el límite: conserve solicitud y respuesta MBAP, configuración autorizada, captura RTU segura y marcas de tiempo. No aumente reintentos ante una dirección ilegal; cambie el mapa o la solicitud.

Flujo de solicitud, respuesta y excepción

Un intercambio normal es PDU de solicitud, envoltura de transporte, envoltura de respuesta, PDU de respuesta y decodificación de aplicación. Para la función 0x03, una respuesta comienza por 03, un recuento de bytes y bytes de registros. Compruebe que el recuento esperado sea cantidad × 2 antes de convertir valores. En valores de varias palabras, conserve las palabras crudas de 16 bits y aplique signo, escala, orden de bytes y orden de palabras documentados en un único paso de conversión probado. Por ejemplo, 41 C8 00 00 representa IEEE-754 25.0 solo bajo un orden especificado; otro orden es otra secuencia de bits, no evidencia de un fallo de red.

Una respuesta de excepción lleva la función solicitada con el bit 7 activado, seguida de un código de excepción. Por ello, una solicitud con función 03 puede recibir 83 02: respuesta de excepción a la función 3, código 2, dirección de datos ilegal. Trátela como un resultado estructurado del protocolo. Función ilegal, dirección de datos ilegal o valor de datos ilegal suelen requerir corregir el mapa documentado o la solicitud. Reintente solo fallos que el equipo y la política de despliegue identifiquen como transitorios; los reintentos duplican tráfico y son especialmente peligrosos cerca de operaciones de escritura. [M-A-P-001]

Fixture determinista y recibo

Ejecute exactamente el siguiente comando en CPython 3.12.3 u otro entorno Python 3 con biblioteca estándar. Valida longitud TCP, campos de transacción y protocolo, vector CRC RTU, recuento normal de bytes y forma de excepción. También rechaza una longitud TCP malformada. No abre una conexión de red ni un puerto serie.

python3 - <<'PY'
def crc16(data):
    crc = 0xFFFF
    for byte in data:
        crc ^= byte
        for _ in range(8):
            crc = (crc >> 1) ^ 0xA001 if crc & 1 else crc >> 1
    return crc

tcp = bytes.fromhex('000100000006110300640002')
assert len(tcp) == 12
assert int.from_bytes(tcp[4:6], 'big') == len(tcp) - 6 == 6
assert tcp[:4] == bytes.fromhex('00010000')
assert tcp[6:] == bytes.fromhex('110300640002')
assert crc16(bytes.fromhex('01030000000A')) == 0xCDC5
normal = bytes.fromhex('110304002A000B')
assert normal[1] == 3 and normal[2] == 4 and len(normal[3:]) == normal[2]
exception = bytes.fromhex('118302')
assert exception[1] == 0x83 and exception[2] == 2
bad = bytes.fromhex('000100000007110300640002')
assert int.from_bytes(bad[4:6], 'big') != len(bad) - 6
print('V-A-P-001 PASS: MBAP, CRC, normal response, exception, malformed length rejected')
PY

Recibo V-A-P-001. Salida esperada: V-A-P-001 PASS: MBAP, CRC, normal response, exception, malformed length rejected. Salida observada el 2026-07-21: exactamente esa línea, estado de salida 0. Entradas de fixture: P-TCP-01, P-RTU-01, respuesta normal 11 03 04 00 2A 00 0B, excepción 11 83 02 y solicitud TCP con longitud malformada. Límite: es un recibo de simulación de codificador y analizador; es BENCH-ONLY—NOT VALIDATED HERE y no puede establecer comportamiento de dispositivo, enrutamiento de pasarela, temporización serie ni seguridad de escritura.

Secuencia de despliegue y decisión entre RTU y TCP

Elija RTU cuando la interfaz es serie y el despliegue controla parámetros, unidad, tiempos y red física. Elija TCP cuando equipos o pasarelas aprobadas exponen Ethernet y la operación se beneficia de enrutamiento IP, supervisión y correlación de transacciones. TCP no elimina el RTU aguas abajo; una pasarela solo desplaza el límite. Prefiera un servidor TCP directo cuando la arquitectura lo admita, pero no sustituya un diseño serie estable solo por una API de socket familiar.

Comience con un único punto de lectura autorizado durante una ventana de mantenimiento. Registre documento fuente y revisión, identificador de unidad, función, desplazamiento, cantidad, solicitud cruda, respuesta cruda, valor decodificado, valor de ingeniería esperado, escala, ordenación, marca de tiempo, autorización y límite de reversión. Si el primer resultado es inverosímil, compare la semántica del mapa antes de culpar al transporte. Si aparecen CRC RTU inválidos, continúe en la guía de capa física; si fallan longitud TCP o comprobaciones de transacción, inspeccione el almacenamiento en búfer, la concurrencia y el límite de pasarela. Escale desde estas simulaciones a un banco aislado y solo después a una prueba de sitio autorizada. Este artículo no autoriza ninguna escritura de producción.

Limitaciones, referencias y lecturas siguientes

Esta guía no cubre todos los mapas de registros de fabricantes, arquitectura de acceso remoto cifrado, política de cola de pasarela, topología RS-485, API de biblioteca ni enclavamiento específico de proceso. Sus fixtures son intencionalmente pequeñas y deterministas para que una revisión pueda reproducir sus límites. No se afirma éxito de hardware. Para cableado, terminación, polarización, ruido y práctica de captura, lea la Guía de supervivencia Modbus RTU. Para disposiciones de solicitudes específicas de función, empaquetado, análisis de respuestas, manejo de excepciones y controles acotados de escritura, lea Códigos de función Modbus.

Referencias

Last verified: 2026-07-21.

Volver al blog

Related Posts

View All Posts »