1. 为什么我要手写Modbus协议栈
去年夏天接到东莞一家注塑厂的设备数据采集需求时,我第一反应也是去找现成的Modbus库。毕竟在C#生态里,像NModbus、EasyModbus这些第三方库名气都不小。但实际用下来才发现,这些"开箱即用"的解决方案在工业现场简直就是灾难。
最让我头疼的是RTU模式的丢包问题。用某知名库测试时,485总线上10台设备同时采集,丢包率竟然高达5%。这意味着每20次采集就会丢失1次数据,对于需要精确控制生产参数的注塑机来说完全不可接受。更糟的是,TCP连接断开后不会自动重连,半夜设备重启后采集就中断了,直到早上工人上班才发现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与基础准备
2.1 硬件环境分析
该注塑厂的设备配置很典型:
- 10台力劲注塑机(Modbus RTU over RS485)
- 5台特灵冷水机(Modbus TCP over Ethernet)
- 1台工控机(Windows 10 IoT,4核CPU/8GB内存)
RS485总线采用手拉手拓扑,终端电阻120Ω,波特率19200bps。网络环境是独立的工业交换机,与办公网络物理隔离。
2.2 协议栈设计目标
基于现场需求,我制定了这些核心指标:
- RTU模式丢包率<0.5%
- TCP断线自动重连间隔<3秒
- 支持协议热切换(无需重启服务)
- 10线程并发读取稳定性
- 平均采集周期<1.5秒
2.3 .NET原生库优势
使用System.IO.Ports和System.Net.Sockets有三大好处:
- 无依赖:部署时不需要带额外DLL
- 可调试:源码级调试比黑盒库方便得多
- 可控性:可以精细调整超时、缓冲等参数
3. Modbus协议核心实现
3.1 RTU模式关键代码
串口配置是稳定性的基础:
csharp复制var port = new SerialPort("COM3", 19200, Parity.None, 8, StopBits.One)
{
ReadTimeout = 300,
WriteTimeout = 300,
Handshake = Handshake.None,
RtsEnable = true
