Modbus RTU 与 Modbus TCP 深入指南-串口服务器:RTU转TCP

十二、串口服务器:RTU转TCP

12.1 典型应用场景

问题:工厂有200个Modbus RTU设备(8条RS485总线,每条25个设备),新MES系统只支持Modbus TCP。

解决方案:使用串口服务器(Serial Device Server)或多端口网关。

12.2 架构图

复制代码
MES/SCADA (TCP Client)
        │
        ├── 网关1 (IP: 192.168.1.10) ── RS485总线1 ── RTU设备(地址1-25)
        │
        ├── 网关2 (IP: 192.168.1.11) ── RS485总线2 ── RTU设备(地址1-25)
        │
        ├── 网关3 (IP: 192.168.1.12) ── RS485总线3 ── RTU设备(地址1-25)
        │
        └── 网关... 

12.3 常见方案对比

方案 优点 缺点 适用场景
单端口串口服务器 简单、便宜 每个总线一个IP 少量RTU设备(<32)
多端口网关 节省IP、管理方便 贵、配置复杂 大量RTU设备
软件网关(如MBpoll) 灵活、可定制 需PC、稳定性一般 测试开发
嵌入式网关(Arduino/Pi) 低成本、可控 需开发、维护 定制化需求

12.4 串口服务器配置要点

12.4.1 常见参数
复制代码
工作模式: TCP Server
监听端口: 502
串口参数: 9600/8/N/1
打包时间: 10ms (或4ms)
打包字节: 200
连接模式: 允许最多5个TCP客户端
12.4.2 地址映射策略
策略 说明 示例
每个网关一个IP 通过IP区分总线 网关1:192.168.1.10, 网关2:192.168.1.11
每个网关一个端口 通过端口区分总线 网关:502→总线1, 503→总线2
单元ID路由 通过MBAP单元ID区分 单元ID1-25→总线1, 26-50→总线2

12.5 实际部署坑点与解决

12.5.1 超时设置问题

问题:网关默认超时200ms,但RTU长距离19200bps下读32个寄存器需280ms。

解决:网关超时调整至500ms。

bash 复制代码
# Moxa NPort配置示例
set timeout=500  # 毫秒
12.5.2 广播风暴

问题:MES误发功能码43(设备识别)扫描所有设备,导致总线阻塞。

解决:网关过滤未实现的功能码。

python 复制代码
# 网关转发逻辑
def forward_filter(pdu):
    func = pdu[0]
    # 只转发常用功能码
    if func in [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0F, 0x10]:
        return True
    else:
        # 返回异常响应(非法功能)
        send_exception(pdu, 0x01)
        return False
12.5.3 连接数限制

问题:多个MES客户端同时访问,但网关只允许1个TCP连接。

解决:使用支持多连接的网关(如Moxa NPort 5150支持5个连接),或前端加负载均衡。

12.6 Python软件网关示例

python

python 复制代码
import socket
import serial
import threading

class ModbusRTUtoTCPGateway:
    def __init__(self, serial_port, baudrate=9600, tcp_port=502):
        self.serial = serial.Serial(serial_port, baudrate, timeout=0.1)
        self.tcp_port = tcp_port
        
    def start(self):
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server.bind(('0.0.0.0', self.tcp_port))
        server.listen(5)
        print(f"Gateway listening on port {self.tcp_port}")
        
        while True:
            client, addr = server.accept()
            print(f"TCP client connected: {addr}")
            threading.Thread(target=self.handle_client, args=(client,)).start()
    
    def handle_client(self, client):
        try:
            while True:
                # 接收TCP请求
                mbap = client.recv(7)
                if len(mbap) < 7:
                    break
                
                trans_id, proto_id, length, unit_id = struct.unpack('>HHHB', mbap)
                pdu = client.recv(length - 1)
                
                # 转换为RTU帧
                rtu_frame = bytes([unit_id]) + pdu
                crc = modbus_crc(rtu_frame)
                rtu_frame += crc.to_bytes(2, 'little')
                
                # 发送到串口
                self.serial.write(rtu_frame)
                
                # 等待RTU响应(3.5字符间隔)
                time.sleep(0.004)  # 4ms
                response = self.serial.read(256)
                
                # 解析RTU响应
                if len(response) < 5:
                    continue
                
                # 验证CRC,提取数据
                recv_crc = (response[-2] << 8) | response[-1]
                calc_crc = modbus_crc(response[:-2])
                if recv_crc != calc_crc:
                    continue
                
                # 转换为TCP响应
                resp_unit_id = response[0]
                resp_pdu = response[1:-2]
                resp_mbap = struct.pack('>HHHB', trans_id, 0, len(resp_pdu)+1, resp_unit_id)
                
                # 发回TCP客户端
                client.send(resp_mbap + resp_pdu)
        except Exception as e:
            print(f"Error: {e}")
        finally:
            client.close()

# 启动网关
gateway = ModbusRTUtoTCPGateway('/dev/ttyUSB0', 9600, 502)
gateway.start()
相关推荐
0+1113 小时前
Linux --从 poll 到 epoll多路转接
linux·服务器·1024程序员节
青瓦梦滋3 小时前
WebSocket协议
linux·服务器·网络·c++·websocket·网络协议·http
桌面运维家4 小时前
旧电脑跑不动课程软件,VDI云桌面怎样接着用?
运维·服务器·虚拟化·pve·vdi·云桌面
zhang133830890754 小时前
传统机械三杯式风速传感器易磨损冻堵?CG-88金属超声波风速风向传感器给出免运维方案
运维·服务器·网络·人工智能·自动化
知已难寻4 小时前
第 2 篇 · 云的地基:服务器、存储、网络三大基础设施
运维·服务器·网络·云原生·云计算·负载均衡·1024程序员节
IpdataCloud6 小时前
批量查IP的API接口怎么选?免费API配额瓶颈与离线库本地批量方案实测
网络·网络协议·tcp/ip
今天重构了吗7 小时前
Linux 上 rm -rf 删错了能找回吗
运维·服务器
ITyunwei09878 小时前
售后夜间值守怎么落地:从告警到交接的工单系统配置笔记
网络
Smoothcloud润云8 小时前
GPU远程纳管安全吗?最小权限、网络边界与日志审计实战
服务器·网络·人工智能·安全·gpu算力·gpu
ai大模型-探索者8 小时前
Function Call与MCP(区别、联系与实战)
java·服务器·网络