用NModbus4实现C# 版Modbus服务器(slave)

NModbus4是一个比较好用的c#版modbus库,既实现了client也实现了Server端(slave)。

可以用其实现一个modbus服务器。注意不是NModbus。这不是一个库。

源码位于 https://github.com/NModbus4/NModbus4

 

一、使用

参考:https://github.com/NModbus4/NModbus4/blob/portable-3.0/Samples/Program.cs 中的实现

_slaveId是设备的id,一般默认是1

_dataStore是存储Modbus数据的对象,可以调用内部函数创建。

            _dataStore = DataStoreFactory.CreateDefaultDataStore();

1.启动服务:

           try
            {
                _ip = new IPAddress(new byte[] {0,0,0,0}); //new IPAddress(new byte[] { 127, 0, 0, 1 });
                _listener = new TcpListener(_ip, _port);
              
                _modbusSlave = ModbusTcpSlave.CreateTcp(_slaveId, _listener);
                _modbusSlave.DataStore = _dataStore;
                _modbusSlave.ModbusSlaveRequestReceived += requestReceiveHandler;

                _thread = new Thread(_modbusSlave.Listen) { Name = _port.ToString() };
                _thread.Start();
                _status = "服务运行中";
                _isRunning = true;
            }
            catch(Exception)
            {
                string errorStr = "[" + _name + "]" + "风机启动失败";
                MessageBox.Show(errorStr, "出错了", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

2.停止服务

执行Dispose()命令就可以,线程停止就可以了。

 _modbusSlave.Dispose();

_thread.Abort();

二、重点注意

1.地址

modbus服务器的数据都存储在 _dataStore 中,一般常用的是组3和组4

           switch(groupindex)
            {
                case 3: return _dataStore.HoldingRegisters; //可修改
                case 4: return _dataStore.InputRegisters;   //不可通过modbus修改
                default: return _dataStore.InputRegisters; 
            }

modbus协议的地址比实际地址多1,_dataStore的地址从1开始,如果写0地址会出异常。

 

2.写值

modbus协议中以寄存器为单位,一个寄存器是16位,如果一次要设置int32的值,需要分别对应到2个寄存器上。

       public void setValue32(int groupindex, int offset, int value)
        {
           byte[] valueBuf =  BitConverter.GetBytes(value);
           ushort lowOrderValue = BitConverter.ToUInt16(valueBuf, 0);
           ushort highOrderValue = BitConverter.ToUInt16(valueBuf, 2);

           ModbusDataCollection data = getRegisterGroup(groupindex);
           data[offset] = lowOrderValue;
           data[offset + 1] = highOrderValue;
        }
        ModbusDataCollection  getRegisterGroup(int groupindex)//根据3或4返回适合的寄存器
        {
            switch(groupindex)
            {
                case 3: return _dataStore.HoldingRegisters; //可修改
                case 4: return _dataStore.InputRegisters;   //不可通过modbus修改
                default: return _dataStore.InputRegisters; 
            }
        }

3.客户端正在从服务器读取数据的时候关闭服务会出异常

 _modbusSlave.Dispose();在服务器工作中可能会出异常,解决办法是修改源码。

修改ModbusMasterTcpConnection.cs中CatchExceptionAndRemoveMasterEndPoint函数

把throw注释掉。

 if (!(ex is IOException || ex is FormatException || ex is ObjectDisposedException))
{
  //throw;
}


 


附上一份完整的源码:

https://github.com/alongL/modbusPlcSimulator

 

 

 

 

 

 

 

你可能感兴趣的:(物联网)