PLC Serial Communication: RS232, RS485, Modbus RTU/TCP & Communication Layers Explained

Understand PLC serial communication from the physical wire up — RS232 vs RS485, TX/RX data flow, Modbus RTU vs TCP framing, and the 7-layer OSI model mapped to industrial protocols.

🔌 The Physical Layer: Where Bits Become Voltage

Before any protocol runs, electricity must flow. This is where RS232 and RS485 live — they define how ones and zeros travel on copper wire.

🧠 Think of It Like a Road System

ConceptRS232RS485
Road typeSingle-lane country roadMulti-lane highway
Distance~15 meters maxUp to 1200 meters
Passengers1 driver, 1 passenger (point-to-point)Up to 32 devices on one bus
Speed vs distanceFast but shortFast AND long
Noise immunityLow (single-ended)High (differential signaling)
---

📡 TX and RX: The Heartbeat of Serial Data

Every serial connection has two fundamental signals:

  • TX (Transmit): Data leaving the device → "I'm talking"
  • RX (Receive): Data arriving at the device → "I'm listening"
  • The Golden Rule of Wiring

    Device A          Device B
    ┌──────┐          ┌──────┐
    │  TX ─┼──────────┼─ RX  │
    │  RX ─┼──────────┼─ TX  │
    │ GND ─┼──────────┼─ GND │
    └──────┘          └──────┘

    TX always connects to RX (crossover) Never TX-to-TX or RX-to-RX!

    RS232 Signal Levels

    Logic 1 (Mark):   -3V to -15V
    Logic 0 (Space):  +3V to +15V

    +15V ┤ ┌───┐ ┌───┐ │ │ │ │ │ ← Logic 0 +3V ┤─ ─ ─│─ ─│─ ─ ─│─ ─│─ ─ ─ 0V ┤ │ │ │ │ -3V ┤─ ─ ─│─ ─│─ ─ ─│─ ─│─ ─ ─ │ ────┘ └─────┘ └──── ← Logic 1 -15V ┤

    RS485 Differential Signaling

                ┌─── Line A (D+) ───┐
    Device ─────┤                   ├───── Device
                └─── Line B (D-) ───┘

    Logic 1: A > B (differential voltage > +200mV) Logic 0: A < B (differential voltage < -200mV)

    Noise hits BOTH lines equally → receiver subtracts it out! This is why RS485 works over 1200m in noisy factories.

    ---

    🏗️ RS232 vs RS485: Decision Matrix

    FeatureRS232RS485
    SignalingSingle-endedDifferential
    Max cable length15m (50 ft)1200m (4000 ft)
    Max devices2 (point-to-point)32 (multidrop bus)
    TopologyPoint-to-pointBus / daisy-chain
    Common usePC-to-PLC debug, HMIFieldbus, sensor networks
    ConnectorDB9 / DB25Screw terminals (A, B, GND)
    Typical baud rates9600–1152009600–921600
    Industrial ratingOffice/labFactory floor

    When to Use Each

    RS232 → Use when:
      ✓ Short distance (< 15m)
      ✓ Only 2 devices talking
      ✓ Programming port / HMI connection
      ✓ Legacy equipment

    RS485 → Use when: ✓ Long distance or noisy environment ✓ Multiple devices on one cable ✓ Modbus RTU network ✓ Industrial sensor bus

    ---

    📦 Modbus: The Universal Industrial Language

    Modbus is a protocol — it defines the meaning of the bytes sent over the wire. Think of RS232/RS485 as the postal truck, and Modbus as the letter format inside.

    Modbus RTU vs Modbus TCP

    FeatureModbus RTUModbus TCP
    TransportRS232 / RS485 serialEthernet (TCP/IP)
    FramingBinary with CRC-16TCP packet with MBAP header
    AddressingStation ID (1–247)IP address + Unit ID
    SpeedUp to 115200 baud10/100 Mbps Ethernet
    Max devices247 per busUnlimited (network limit)
    Error checkCRC-16 checksumTCP built-in + optional
    Cable2-wire (RS485) or 3-wire (RS232)Cat5/Cat6 Ethernet

    Modbus RTU Frame Structure

    ┌──────────┬───────────┬──────────────┬──────────┐
    │ Slave ID │ Function  │    Data      │  CRC-16  │
    │ (1 byte) │ (1 byte)  │ (N bytes)    │ (2 bytes)│
    └──────────┴───────────┴──────────────┴──────────┘
         │           │            │              │
         │           │            │              └─ Error detection
         │           │            └─ Register addresses & values
         │           └─ Read (03), Write Single (06), Write Multi (16)
         └─ Which device responds (1–247)

    Frame gap: 3.5 character times of silence = end of frame

    Modbus TCP Frame (MBAP Header)

    ┌──────────────┬────────────┬────────┬─────────┬───────────┬──────────┐
    │ Transaction  │ Protocol   │ Length │ Unit ID │ Function  │   Data   │
    │ ID (2 bytes) │ ID (2 bytes│(2 bytes│(1 byte) │ (1 byte)  │(N bytes) │
    │              │  = 0x0000) │       │         │           │          │
    └──────────────┴────────────┴────────┴─────────┴───────────┴──────────┘
                                             │
                                             └─ Same as RTU slave ID
    No CRC needed — TCP handles error detection!
    

    Common Modbus Function Codes

    CodeNameDescription
    01Read CoilsRead digital outputs (ON/OFF)
    02Read Discrete InputsRead digital inputs
    03Read Holding RegistersRead analog/config values (most common)
    04Read Input RegistersRead analog input values
    05Write Single CoilSet one digital output
    06Write Single RegisterSet one register value
    15Write Multiple CoilsSet multiple digital outputs
    16Write Multiple RegistersSet multiple register values
    ---

    🌐 The 7-Layer OSI Model for Industrial Communication

    The OSI model explains why we need different things like RS485 (physical) and Modbus (application). Each layer has a job:

    Layer 7 │ APPLICATION  │ Modbus commands, read/write registers
    ────────┤──────────────┤─────────────────────────────────────
    Layer 6 │ PRESENTATION │ Data encoding (big-endian, ASCII vs RTU)
    ────────┤──────────────┤─────────────────────────────────────
    Layer 5 │ SESSION      │ Request/response pairing, timeouts
    ────────┤──────────────┤─────────────────────────────────────
    Layer 4 │ TRANSPORT    │ TCP (reliable) or UDP (fast)
    ────────┤──────────────┤─────────────────────────────────────
    Layer 3 │ NETWORK      │ IP addressing, routing between subnets
    ────────┤──────────────┤─────────────────────────────────────
    Layer 2 │ DATA LINK    │ Framing, MAC addresses, CRC checks
    ────────┤──────────────┤─────────────────────────────────────
    Layer 1 │ PHYSICAL     │ RS232/RS485 voltages, cables, connectors
    

    Where Industrial Protocols Live

    Protocol          │ Layer 1      │ Layer 2-4        │ Layer 7
    ──────────────────┤──────────────┤──────────────────┤──────────────
    Modbus RTU        │ RS232/RS485  │ Serial framing   │ Modbus
    Modbus TCP        │ Ethernet     │ TCP/IP           │ Modbus
    EtherNet/IP       │ Ethernet     │ TCP/UDP + IP     │ CIP
    PROFINET          │ Ethernet     │ TCP/UDP + RT     │ PROFINET IO
    PROFIBUS DP       │ RS485        │ Token passing    │ PROFIBUS
    EtherCAT          │ Ethernet     │ On-the-fly       │ CoE/SoE
    OPC UA            │ Ethernet     │ TCP/IP           │ OPC UA Binary
    

    ---

    💻 Structured Text: Modbus RTU Communication

    PROGRAM ModbusRTUMaster
    VAR
        // Serial port configuration
        SerialConfig : COM_CONFIG;
        
        // Modbus request
        mbRequest : MODBUS_REQUEST;
        mbSend : BOOL := FALSE;
        mbBusy : BOOL;
        mbDone : BOOL;
        mbError : BOOL;
        
        // Data buffers
        HoldingRegs : ARRAY[0..9] OF WORD;  // Read from slave
        WriteRegs   : ARRAY[0..4] OF WORD;  // Write to slave
        
        // Communication state machine
        CommState : INT := 0;
        PollTimer : TON;
        TimeoutTimer : TON;
        RetryCount : INT := 0;
        MAX_RETRIES : INT := 3;
    END_VAR

    // ─── Serial Port Setup (done once) ─── SerialConfig.Port := 1; // COM1 SerialConfig.BaudRate := 19200; // Match slave setting SerialConfig.DataBits := 8; SerialConfig.StopBits := 1; SerialConfig.Parity := 'E'; // Even parity (Modbus standard) SerialConfig.Timeout := T#1S; // 1 second timeout

    // ─── Communication State Machine ─── CASE CommState OF 0: // IDLE — Wait for poll interval PollTimer(IN := TRUE, PT := T#500MS); IF PollTimer.Q THEN PollTimer(IN := FALSE); CommState := 10; END_IF; 10: // SEND READ REQUEST mbRequest.SlaveID := 1; // Target device address mbRequest.FunctionCode := 3; // Read Holding Registers mbRequest.StartAddress := 40001; // First register mbRequest.Quantity := 10; // Read 10 registers mbSend := TRUE; TimeoutTimer(IN := FALSE); CommState := 20; 20: // WAIT FOR RESPONSE TimeoutTimer(IN := TRUE, PT := T#2S); IF mbDone THEN // Success — copy data HoldingRegs := mbRequest.ResponseData; RetryCount := 0; CommState := 30; // Next: write ELSIF mbError OR TimeoutTimer.Q THEN // Failed — retry logic RetryCount := RetryCount + 1; IF RetryCount >= MAX_RETRIES THEN // Log alarm, skip to next cycle RetryCount := 0; CommState := 0; ELSE CommState := 10; // Retry END_IF; END_IF; 30: // SEND WRITE REQUEST mbRequest.SlaveID := 1; mbRequest.FunctionCode := 16; // Write Multiple Registers mbRequest.StartAddress := 40101; mbRequest.Quantity := 5; mbRequest.WriteData := WriteRegs; mbSend := TRUE; CommState := 40; 40: // WAIT FOR WRITE CONFIRMATION TimeoutTimer(IN := TRUE, PT := T#2S); IF mbDone OR mbError OR TimeoutTimer.Q THEN CommState := 0; // Back to idle END_IF; END_CASE;

    ---

    🔧 Modbus TCP Client in Structured Text

    PROGRAM ModbusTCPClient
    VAR
        // TCP connection
        tcpConnect : TCP_CONNECT;
        tcpConnected : BOOL;
        ServerIP : STRING := '192.168.1.100';
        ServerPort : UINT := 502;  // Standard Modbus TCP port
        
        // Modbus TCP transaction
        TransactionID : UINT := 0;
        mbTCPRequest : MODBUS_TCP_REQUEST;
        
        // Read data from remote I/O module
        RemoteInputs  : ARRAY[0..15] OF WORD;
        RemoteOutputs : ARRAY[0..7] OF WORD;
        
        // Diagnostics
        CommOK : BOOL;
        ResponseTime : TIME;
        RequestTimestamp : TIME;
        PacketsSent : UDINT;
        PacketsReceived : UDINT;
        PacketsLost : UDINT;
    END_VAR

    // ─── Build Modbus TCP Request ─── TransactionID := TransactionID + 1;

    mbTCPRequest.TransactionID := TransactionID; mbTCPRequest.ProtocolID := 0; // Always 0 for Modbus mbTCPRequest.UnitID := 1; // Slave/unit identifier mbTCPRequest.FunctionCode := 3; // Read Holding Registers mbTCPRequest.StartAddress := 0; mbTCPRequest.Quantity := 16;

    // ─── Send and Track ─── IF tcpConnected THEN RequestTimestamp := TIME(); // ... send mbTCPRequest over TCP socket ... PacketsSent := PacketsSent + 1; END_IF;

    // ─── Response Handling ─── IF ResponseReceived THEN ResponseTime := TIME() - RequestTimestamp; PacketsReceived := PacketsReceived + 1; CommOK := TRUE; // Validate transaction ID matches IF Response.TransactionID = TransactionID THEN RemoteInputs := Response.Data; END_IF; ELSIF ResponseTimeout THEN PacketsLost := PacketsLost + 1; CommOK := FALSE; END_IF;

    ---

    🛡️ Common Communication Errors & Fixes

    SymptomLikely CauseFix
    No response at allTX/RX wired wrongSwap TX and RX wires
    Garbled dataBaud rate mismatchMatch all devices to same baud
    CRC errorsParity mismatchSet all devices to same parity (Even/None)
    Intermittent timeoutCable too long for RS232Switch to RS485 for >15m
    Multiple slaves conflictSame address on busAssign unique IDs 1–247
    Modbus TCP refusedWrong port or firewallUse port 502, check firewall rules
    Data swapped (byte order)Endianness mismatchCheck big-endian vs little-endian
    ---

    📊 Protocol Selection Flowchart

                        ┌─────────────────┐
                        │  How far is the  │
                        │    device?       │
                        └────────┬────────┘
                                 │
                     ┌───── < 15m ──────┐──── > 15m ────┐
                     │                  │                │
                ┌────▼────┐       ┌────▼────┐      ┌────▼────┐
                │ RS232   │       │ RS485   │      │ Ethernet│
                │ OK      │       │ Modbus  │      │ Modbus  │
                │         │       │ RTU     │      │ TCP     │
                └─────────┘       └─────────┘      └─────────┘
                     │                  │                │
                1 device          Up to 32         Unlimited
                Debug/HMI         Sensors/VFDs     SCADA/MES
    

    Summary

    Serial communication is the nervous system of any PLC network. Understanding the difference between the physical layer (RS232/RS485 voltages and wiring) and the protocol layer (Modbus RTU/TCP commands) is essential for every automation engineer. RS232 is your quick debug cable; RS485 is your factory backbone; Modbus is the common language they all speak. Master these layers, and commissioning any industrial network becomes systematic rather than guesswork.