Хочу закрыть этот вопрос окончательно.

У OPC Lectus есть возможность добавлять узлы работающие через такие вот ретрансляторы:
Lectus.jpg
А так как он является OPC-сервером, то интегрируется с любой Scada.

Будет полезно новичкам, как пример использования библиотеки UNM.lib и как возможность организации доступа нескольких мастеров в одну RS485-сеть.
Видео испытания кода

ModbusGate.JPG

Код:
PROGRAM PLC_PRG
VAR
	Port: DWORD := 255;
	State: INT := 0; (* Состояние ретранслятора *)
	Addr: BYTE := 1; (* Адрес ретранслятора - задается перед заливкой в ПЛК *)
	CRC: WORD; (* Контрольная сумма пакетов *)
	Timeout: TIME := T#50ms; (* Таймаут ожидания ответного пакета из нижней сети - задается перед заливкой в ПЛК *)
	pBuf: POINTER TO STRING;
	pByte: POINTER TO BYTE;
	IN: POINTER TO RBDATA; (* Принятый байт *)
	TMR: TON; (* Таймер отсчета таймаутов *)
	HeadTCP: ARRAY[1..4] OF BYTE; (* Заголовок ModbusTCP *)
	Buf: ARRAY [1..128] OF BYTE; (* Буфер *)
	Item: INT;
	Count: WORD;
END_VAR

CASE State OF

    0:    (* Выполняем захват всех UNM-устройств *)
        IF LockDevice(0) = 1 AND LockDevice(1) = 1 AND LockDevice(2) = 1 THEN
            Count := 0; State := 1;
        END_IF

    1:    (* Прием пакета с верхней сети  *)
        IF Port = 255 THEN                                                                                (* Пока ждем кто начнет первым *)

             IN := GetByte(0);                                                                                (* Слушаем TCP *)
            IF IN > 0 THEN
                Port := 0; Count := 1; Buf[Count] := IN^.data;                                                (* Итак TCP был первым *)
            ELSE
                 IN := GetByte(1);                                                                            (* Слушаем RS232 *)
                IF IN > 0 THEN
                    Port := 1; Count := 1; Buf[Count] := IN^.data;                                            (* Итак RS-232 был первым *)
                END_IF
            END_IF

        ELSE                                                                                                (* Здесь кто был первым уже известно *)

            IN := GetByte(Port);                                                                       (* Принимаем очередной байт *)
            IF IN > 0 THEN
                TMR(IN:=FALSE); Count := Count + 1; Buf[Count] := IN^.data;         (* И сохраняем в буфер *)
            ELSE
                IF Count > 0 THEN
                    TMR(IN := TRUE, PT := T#1ms);                                                        (* Здесь желательно установить PT:= 3.5/(Baudrate*10) *)
                    IF TMR.Q  THEN                                                                        (* Прем пакета завершен *)
                        TMR(IN:=FALSE);
                        IF Count >= 5 THEN                                                                (* Длина пакета достаточна для анализа *)

                            CASE Port OF

                                0:    (* Обработка ModbusTCP-пакета *)
                                    FOR CRC := 1 TO 4 DO                                                        (* Сохраним заголовок ModbusTCP-пакета *)
                                        HeadTCP[CRC] := Buf[CRC];
                                    END_FOR
                                    pByte := ADR(Buf) + 6; CRC := CalcCRC(pByte, Count - 6);                    (* Вычислим CRC *)
                                    pByte := ADR(Buf) + Count; pByte^ := WORD_TO_BYTE(CRC MOD 256);    (* Добавляем младший байт CRC *)
                                    pByte := pByte + 1; pByte^ := WORD_TO_BYTE(CRC / 256);                    (* Добавляем старший байт CRC *)
                                    pBuf := ADR(Buf) + 6; SetByte(2, pBuf^, Count - 4);                            (* Отправляем в порт RS485-1 *)
                                    Count := 0; State := 2;                                                            (* Переходим к ожиданию ответа *)

                                1:    (* Обработка ModbusRTU-пакета *)
                                    pByte := ADR(Buf); CRC := CalcCRC(pByte, Count - 2);                        (* Вычисляем CRC *)
                                    pByte := ADR(Buf) + Count - 2;
                                    IF pByte^ = (CRC MOD 256) THEN                                            (* Проверяем младший байт CRC *)
                                        pBYte := ADR(Buf) + Count - 1;
                                        IF pByte^ = (CRC / 256) THEN                                            (* Проверяем старший байт CRC *)
                                            pByte := ADR(Buf);
                                            IF pByte^ = Addr THEN                                                (* Проверяем адрес ретранслятора *)
                                                pBuf := ADR(Buf) + 1; SetByte(2, pBuf^, Count - 3);                (* Отправляем в RS485 встроенный пакет *)
                                                Count := 0; State := 2;                                                (* Переходим к ожиданию ответа *)
                                            ELSE
                                                Count := 0; Port := 255;                                            (* Пакет не нам - ждем следующий *)
                                            END_IF
                                        ELSE
                                            Count :=0; Port := 255;                                                (* Неверный CRC - ждем следующий *)
                                        END_IF
                                    ELSE
                                        Count := 0; Port := 255;                                                    (* Неверный CRC - ждем следующий *)
                                    END_IF
                            END_CASE

                        ELSE
                            Count := 0; Port := 255;                                                                (* Пакет слишком маленький - ждем следующий *)
                        END_IF
                    END_IF                                                                                        (* Ожидаем окончание приема *)
                END_IF                                                                                            (* Ожидаем входной пакета *)
            END_IF                                                                                                (* Ожидаем очередной байт *)
        END_IF                                                                                                    (* Ожидаем первый байт для определения первого UNM *)

    2:    (* Ожидание ответного пакета из нижней сети *)
        IN := GetByte(2);
        IF IN > 0 THEN
            TMR(IN := FALSE); Count := Count + 1; Buf[Count] := IN^.data;
        ELSE
            IF Count = 0 THEN
                TMR(IN := TRUE, PT := Timeout);
                IF TMR.Q THEN
                    TMR(IN:=FALSE); Count := 0; Port := 255; State := 1;                        (* Нет ответа - начинаем все с начала*)
                END_IF
            ELSE
                TMR(IN := TRUE, PT := T#1ms);                                                (* Контроль окончания приема *)
                IF TMR.Q THEN                                                                (* Окончание приема *)
                    TMR(IN:=FALSE);

                    pByte := ADR(Buf); CRC := CalcCRC(pByte, Count - 2);
                    pByte := ADR(Buf) + Count - 2;
                    IF pByte^ = (CRC MOD 256) THEN
                        pByte := ADR(Buf) + Count - 1;
                        IF pByte^ = (CRC / 256) THEN

                            CASE Port OF

                                0:    (* Заворачиваем ModbusTCP *)
                                    FOR Item := Count + 7 TO 7 BY -1 DO                            (* Сдвинем буфер на 6 байт вправо*)
                                        Buf[Item] := Buf[Item - 6];
                                    END_FOR
                                    FOR Item := 1 TO 4 DO                                            (* Вернем заголовок ModbusTCP *)
                                        Buf[Item] := HeadTCP[Item];
                                    END_FOR
                                    pByte := ADR(Buf) + 4; pByte^ := WORD_TO_BYTE((Count -2) / 256);                (* Добавим CRC *)
                                    pByte := ADR(Buf) + 5; pByte^ := WORD_TO_BYTE((Count-2) MOD 256);
                                    pBuf := ADR(Buf); SetByte(0, pBuf^, Count + 4);                    (* Вернем верхней сети 6(Head) + Count - 2(CRC) *)
                                    Count := 0; Port := 255; State := 1;                                (* И начнем все с начала *)

                                1:    (* Заворачиваем в  ModbusRTU *)
                                    FOR Item := Count + 2 TO 2 BY -1 DO                            (* Сдвигаем буфер на 1 байт вправо *)
                                        Buf[Item] := Buf[Item-1];
                                    END_FOR
                                    pByte := ADR(Buf); pByte^ := Addr;                                (* Добавляем адрес ретранслятора *)
                                    CRC := CalcCRC(pByte, Count + 1);                                (* Рассчитаем CRC нового пакета *)
                                    pByte := ADR(Buf) + Count + 1; pByte^ := WORD_TO_BYTE(CRC MOD 256);        (* Добавим младший байт CRC *)
                                    pByte := ADR(Buf) + Count + 2; pByte^ := WORD_TO_BYTE(CRC / 256);            (* Добавим старший байт CRC *)
                                    pBuf := ADR(Buf); SetByte(1, pBuf^, Count + 3);                        (* Вернем верхней сети 1(Addr) + Count + 2(CRC) *)
                                    Count := 0; Port := 255; State := 1;                                (* И начнем все с начала *)

                            END_CASE
                        ELSE
                            Count :=0; Port := 255; State := 1;                                    (* Неверна CRC - все с начала *)
                        END_IF
                    ELSE
                            Count :=0; Port := 255; State := 1;                                    (* Неверна CRC - все с начала *)
                    END_IF
                END_IF                                                                        (* Ожидание окончания приема *)
            END_IF                                                                            (* Ожидаем очередной байт *)
        END_IF                                                                                (* Ожидаем входной пакет *)

END_CASE
Код:
FUNCTION CalcCRC : WORD
VAR
	Cnt: BYTE;
END_VAR
VAR_INPUT
	pData: POINTER TO BYTE;
	Size: WORD;
END_VAR

(* Вычисление контрольной суммы MODBUS RTU CRC *)
CalcCRC := 16#FFFF;
WHILE Size > 0 DO
	CalcCRC := CalcCRC XOR pData^;
	FOR Cnt := 0 TO 7 DO
		IF CalcCRC.0 = 0 THEN
			CalcCRC := SHR(CalcCRC, 1);
		ELSE
			CalcCRC := SHR(CalcCRC, 1) XOR 16#A001;
		END_IF
	END_FOR;
	pData := pData + 1;
	Size := Size - 1;
END_WHILE