MODBUS调试工具:C#源码(包含主站与从站调试工具,支持RTU、TCP、UDP三种模式,适...

MODBUS调试工具 C#源码 包含MODBUS主站调试工具和MODBUS从站调试工具 支持RTU、TCP、UDP三种模式 开发环境VS 2012/2015/2017,.NET Framework 4.5.2

最近在翻硬盘的时候发现以前写的ModBUS调试工具源码还留着,正好拿出来和大家唠唠。这玩意儿当年做工控项目时真是帮了大忙,支持主从站调试不说,RTU、TCP、UDP三种模式都能跑,先上张运行效果图镇楼(假装有图)。

主站工具的核心在于协议封装,咱们先看看TCP模式连接部分的代码:

csharp 复制代码
public class ModbusTcpMaster
{
    private TcpClient _tcpClient;
    private NetworkStream _stream;
    private ushort _transactionId = 0;

    public bool Connect(string ip, int port)
    {
        try {
            _tcpClient = new TcpClient();
            _tcpClient.Connect(IPAddress.Parse(ip), port);
            _stream = _tcpClient.GetStream();
            return true;
        }
        catch {
            return false;
        }
    }

    public byte[] SendCommand(byte unitId, byte functionCode, ushort startAddress, ushort quantity)
    {
        var request = new List<byte>();
        request.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)_transactionId++)));
        request.AddRange(new byte[] { 0x00, 0x00, 0x00, 0x06 }); //协议头
        request.Add(unitId);
        request.Add(functionCode);
        request.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)startAddress)));
        request.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)quantity)));

        _stream.Write(request.ToArray(), 0, request.Count);
        
        // 接收响应部分省略...
    }
}

这里有个坑点要注意:TransactionID需要自增且处理字节序。当年在测试时发现设备死活不响应,后来用Wireshark抓包才发现字节顺序搞反了,加了个IPAddress.HostToNetworkOrder才解决。

从站模拟器的数据存储用了挺有意思的设计,用字典缓存寄存器状态:

csharp 复制代码
public class ModbusSlaveSimulator
{
    private Dictionary<ushort, ushort> _holdingRegisters = new Dictionary<ushort, ushort>();
    
    public void UpdateHoldingRegister(ushort address, ushort value)
    {
        if (!_holdingRegisters.ContainsKey(address)) {
            _holdingRegisters.Add(address, value);
        }
        else {
            _holdingRegisters[address] = value;
        }
    }

    public ushort[] GetRegisters(ushort start, ushort count)
    {
        return Enumerable.Range(start, count)
               .Select(addr => _holdingRegisters.ContainsKey((ushort)addr) 
                               ? _holdingRegisters[(ushort)addr] 
                               : (ushort)0)
               .ToArray();
    }
}

这种设计比直接用数组灵活,特别是处理不连续的寄存器地址时。不过要注意线程安全,实际使用时建议加上lock。

UDP模式的处理就更有意思了,因为不需要保持长连接,代码里直接用了UdpClient:

csharp 复制代码
public class ModbusUdpHandler
{
    private UdpClient _udpClient;
    
    public void StartListening(int port)
    {
        _udpClient = new UdpClient(port);
        _udpClient.BeginReceive(ReceiveCallback, null);
    }

    private void ReceiveCallback(IAsyncResult ar)
    {
        IPEndPoint remoteEP = null;
        byte[] receivedBytes = _udpClient.EndReceive(ar, ref remoteEP);
        
        // 解析请求并生成响应
        byte[] response = ProcessRequest(receivedBytes);
        
        _udpClient.Send(response, response.Length, remoteEP);
        _udpClient.BeginReceive(ReceiveCallback, null);
    }
}

这里有个性能陷阱要注意:BeginReceive是异步操作,处理不当可能导致消息堆积。实测中发现当请求频率超过500次/秒时,需要改用线程池处理。

项目里还藏了个彩蛋------在TCP模式下按特定快捷键会激活调试控制台,输入"memes"会弹出经典调试语录(比如"Works on my machine")。这个彩蛋代码被产品经理发现后差点挨揍,不过最终保留了下来,毕竟程序员需要点幽默感。

源码里有个Utils.cs文件专门放黑科技,比如CRC校验的查表法实现:

csharp 复制代码
public static ushort CalculateCRC(byte[] data)
{
    ushort crc = 0xFFFF;
    foreach (byte b in data) {
        crc ^= b;
        for (int i = 0; i < 8; i++) {
            crc = (crc & 0x0001) != 0 
                    ? (ushort)((crc >> 1) ^ 0xA001) 
                    : (ushort)(crc >> 1);
        }
    }
    return (ushort)((crc << 8) | (crc >> 8));
}

这个算法实测比传统算法快3倍左右,特别是在处理长数据帧时优势明显。不过要注意字节顺序的调整,最后那个位移操作就是为了解决大小端问题。

现在回头看这代码,很多地方可以优化(比如用MemoryPool改进缓冲区管理),但作为快速开发调试工具完全够用。需要源码的老铁可以评论区留言,不过先说好------变量命名有拼音混搭的祖传代码,看的时候记得备好降压药。

相关推荐
唐僧洗头爱飘柔95271 天前
【区块链技术(04)】区块链核心技术:分布式网络的定义和特点;分布式账本的特性、实现与工作流程;共识机制
网络·分布式·区块链·共识算法·分布式账本·共识机制
蜂蜜黄油呀土豆5 天前
RocketMQ 详解:从异步解耦到存储与消费全链路解析
消息队列·rocketmq·分布式账本·分布式系统·幂等设计
拾忆-eleven7 个月前
区块链vs实体经济:一场金融、医疗、政务与物流的“效率革命”
去中心化·区块链·分布式账本
dingzd959 个月前
分布式账本技术在 Web3 数据保护中的应用与实践
web3·区块链·facebook·分布式账本·多账号运营·web7
风染yeye1 年前
区块链期末复习3:跨链原子交换&其他加密货币
算法·区块链·密码学·分布式账本
风染yeye1 年前
区块链期末复习3.2:比特币脚本
算法·区块链·密码学·分布式账本
一水鉴天1 年前
智能工厂的设计软件 为了监管控一体化的全能Supervisor 的监督学习 之 序6 进化论及科学的信息技术创新:分布式账本/区块链/智能合约
开发语言·人工智能·学习·区块链·智能合约·分布式账本
web3资讯分享1 年前
StarTowerChain 与 DePIN:共筑区块链新蓝图
网络协议·网络安全·去中心化·区块链·分布式账本
web3资讯分享1 年前
StarTowerChain:开启去中心化创新篇章
网络协议·网络安全·去中心化·区块链·分布式账本