ETJava Beta | Java    注册   登录
  • 搜索:
  • C#轻松实现Modbus通信

    发表于      阅读(1)     博客类别:Crawler     转自:https://www.cnblogs.com/xiketangedu/p/18461727
    如有侵权 请联系我们删除  (页面底部联系我们)  

    1、前言

    大家好!我是付工。前面给大家介绍了一系列关于RS485与Modbus的知识。

    终于有人把RS485说清楚了
    终于有人把Modbus说明白了
    通透!终于把ModbusRTU弄明白了
    这样看来,ModbusTCP协议太简单了
    今天跟大家聊聊关于C#如何实现Modbus通信。

    2、开源通信库

    通信库是对通信协议的封装,一般是以dll动态链接库的形式存在,对于编程者来说,只需要调用库的各种方法即可实现数据读写。

    通信库有两种,一种是开源的,即使开源,也要注意看下开源许可证,开源并不一定免费,另外一种就是自己开发封装的,这个需要具备一定的开发能力。

    Modbus通信有很多开源通信库,这其中使用较为广泛的是NModbus4,NModbus4是一个开源且免费的Modbus通信库,它的开源许可证是MIT,是一个相对宽松的软件授权条款,可以商用。

    3、ModbusRTU通信

    1、在项目解决方案资源管理器中,选择【引用】右击,在弹出的界面中,点击【管理NuGet程序包】选项,如下图所示:

     

    2、在打开的选项卡中,选择【浏览】,然后输入NModbus4进行搜索,搜索到之后,选择最新稳定版2.1.0,点击【安装】即可:

     

    3、在NModbus4基础上封装一个打开串口和关闭串口的方法:

    private SerialPort serialPort;
    private ModbusSerialMaster master;
    public void Open(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
    {
        if (this.serialPort != null && this.serialPort.IsOpen)
        {
            this.serialPort.Close();
        }
        this.serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
        this.serialPort.Open();
        this.master = ModbusSerialMaster.CreateRtu(this.serialPort);
        this.master.Transport.WriteTimeout = 2000;
        this.master.Transport.ReadTimeout = 2000;
        this.master.Transport.WaitToRetryMilliseconds = 500;
        this.master.Transport.Retries = 3;
    }
     public void Close()
     {
         if (this.serialPort != null && this.serialPort.IsOpen)
         {
             this.serialPort.Close();
         }
         this.master = null;
     }

    4、在NModbus4基础上封装各种读写的方法,这里以读取保持型寄存器为例,其他方法都是类似的:

    public byte[] ReadHoldingRegisters(byte slaveId, ushort start, ushort length)
    {
        try
        {
            ushort[] data = this.master.ReadHoldingRegisters(slaveId, start, length);
            List<byte> result = new List<byte>();
            foreach (var item in data)
            {
                result.AddRange(BitConverter.GetBytes(item).Reverse());
            }
            return result.ToArray();
        }
        catch (Exception ex)
        {
            throw new Exception("【读取保持寄存器】失败:" + ex.Message);
        }
    }
    基于NModbus4实现ModbusRTU通信,不需要关注协议及报文,只需要对NModbus4库二次封装即可。

    4、ModbusTCP通信

    NModbus4不仅支持ModbusRTU通信,也同样支持ModbusTCP通信,ModbusTCP与ModbusRTU的封装过程非常类似,主要是存在以下两个不同点:

    • ModbusRTU是基于串口通信,因此主要使用的是SerialPort类,而ModbusTCP是基于以太网通信,主要使用的是TcpClient类。

    • ModbusRTU的读取和写入方法中都必须包含从站地址,而ModbusTCP可以把SlaveAddress作为一个可选项。

    ModbusTCP通信库封装过程如下:1、在NModbus4基础上封装一个TCP连接和断开的方法:
    private TcpClient tcpClient;
    private ModbusIpMaster master
    public void Connect(string ip, int port)
    {
        tcpClient = new TcpClient();
        tcpClient.Connect(IPAddress.Parse(ip), port);
        this.master = ModbusIpMaster.CreateIp(this.tcpClient);
        this.master.Transport.WriteTimeout = 2000;
        this.master.Transport.ReadTimeout = 2000;
        this.master.Transport.WaitToRetryMilliseconds = 500;
        this.master.Transport.Retries = 3;
    }
     public void DisConnect()
     {
         if (this.tcpClient != null && this.tcpClient.Connected)
         {
             this.tcpClient.Close();
         }
         this.master = null;
     }
    2、封装一个读取输出线圈的方法,其他读写方法都是类似的:
    public bool[] ReadOutputCoils(ushort start, ushort length, byte slaveAddress = 1)
    {
        try
        {
            return this.master.ReadCoils(slaveAddress, start, length);
        }
        catch (Exception ex)
        {
            throw new Exception("【读取输出线圈】失败:" + ex.Message);
        }
    }