C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用

NModbus的主站开发

1.开发环境要求:PC端作为主站,控制器作为从站

2.PC端初始化代码:

serialPort = new SerialPort();
serialPort.PortName = "COM1";
serialPort.BaudRate = 9600;
serialPort.DataBits = 8;
serialPort.StopBits = StopBits.One;
serialPort.Parity = Parity.Even;
master = ModbusSerialMaster.CreateRtu(serialPort);
master.Transport.ReadTimeout = 2000;
master.Transport.Retries = 10;
master.Transport.WriteTimeout = 2000;
serialPort.Open();

3.PC端读写代码:(slaveNum:从站Slave ID,addrNum:读取寄存器起始地址,len:读取寄存器长度)功能码03

ushort[] recv = master.ReadHoldingRegisters((byte)slaveNum, (ushort)addrNum, (byte)len);

4.控制器收到指令格式:

如0A 03 9C 47 00 01 1B 34

0A-SlaveID

03-功能码 

9C-寄存器地址高位

47 -寄存器地址低位

00 -读取长度高位

01-读取长度低位

1B 34-校验位

5.Modbus Slave工具测试

  • 设置Connection-Connection Setup,根据上面设置RTU连接方式,Modbus Slave设置如下:(Master设置的串口参数必须如下的配置相同

C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用_第1张图片

  • 设置SetUp-Slave Definition,Master设置的SlaveID必须跟下图配置的保持一致,Function:功能码,Address:显示的寄存器起始地址,Quanity:寄存器的数量

C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用_第2张图片

  • 配置完成后点击连接,连接成功后的状态如下:

C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用_第3张图片

  • 查看通讯数据帧,界面的Display-Communication…功能

C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用_第4张图片

Modbus的从站开发

1.开发环境要求:PC作为从站,控制器作为主站,从站启动监听,触发事件,更新数据库至DataStore

2.PC端初始化代码:

comPort.PortName = "COM1";
comPort.BaudRate = 9600;
comPort.DataBits = 8;
comPort.Parity = Parity.Even;
comPort.StopBits = StopBits.One;
comPort.Open();
slave = ModbusSerialSlave.CreateRtu(slaveID, comPort);
slave.ModbusSlaveRequestReceived += new EventHandler(Modbus_Request_Event);
slave.DataStore = Modbus.Data.DataStoreFactory.CreateDefaultDataStore();
slave.DataStore.DataStoreWrittenTo += new EventHandler(Modbus_DataStoreWriteTo);
slave.Listen();

主站触发请求事件代码:

private void Modbus_Request_Event(object sender, Modbus.Device.ModbusSlaveRequestEventArgs e)
{
    try
    {
        //request from master
        byte fc = e.Message.FunctionCode;
        byte[] data = e.Message.MessageFrame;
        byte[] byteStartAddress = new byte[] { data[3], data[2] };
        byte[] byteNum = new byte[] { data[5], data[4] };
        Int16 StartAddress = BitConverter.ToInt16(byteStartAddress, 0);
        Int16 NumOfPoint = BitConverter.ToInt16(byteNum, 0);

        BOOL = true;

        FCNUM = fc.ToString();
        /*
        if (fc.ToString() == "6")
        {
            //AO
            slave.DataStore.HoldingRegisters[StartAddress] = 16;
            slave.DataStore.HoldingRegisters[StartAddress + 1] = 17;
        }
        */
        Console.WriteLine(fc.ToString() + "," + StartAddress.ToString() + "," + NumOfPoint.ToString());
    }
    catch (Exception exc)
    {
        FormMainUn.runStatusFile.WriteString("", "readReg", "3");
        FormMainUn.runStatusFile.WriteString("","readRegErrorMsg",exc.Message);
        MessageBox.Show(exc.ToString());
    }

}

写DataStore事件代码:

private void Modbus_DataStoreWriteTo(object sender, Modbus.Data.DataStoreEventArgs e)
        {
            //this.Text = "DataType=" + e.ModbusDataType.ToString() + "  StartAdress=" + e.StartAddress;
            int iAddress = e.StartAddress;//e.StartAddress;
            switch (e.ModbusDataType)
            {
                case ModbusDataType.HoldingRegister:
                    for (int i = 0; i < e.Data.B.Count; i++)
                    {
                        //Set AO                 
                        slave.DataStore.HoldingRegisters[e.StartAddress + i + 1] = e.Data.B[i];
                        //e.Data.B[i] already write to slave.DataStore.HoldingRegisters[e.StartAddress + i + 1]
                        //e.StartAddress starts from 0
                        //You can set AO value to hardware here

                        //DoAOUpdate(iAddress, e.Data.B[i].ToString());
                        iAddress++;
                    }
                    break;

                case ModbusDataType.Coil:
                    for (int i = 0; i < e.Data.A.Count; i++)
                    {
                        //Set DO
                        slave.DataStore.CoilDiscretes[e.StartAddress + i + 1] = e.Data.A[i];
                        //e.Data.A[i] already write to slave.DataStore.CoilDiscretes[e.StartAddress + i + 1]
                        //e.StartAddress starts from 0
                        //You can set DO value to hardware here

                        //DoDOUpdate(iAddress, e.Data.A[i]);
                        iAddress++;
                        if (e.Data.A.Count == 1)
                        {
                            break;
                        }
                    }
                    break;
            }

        }

3.PC读数据代码:

public void PCReadDatafromPC(ushort RAddress, out int data)
{
    int AOAddress;
    RAddresstoAOAddress(RAddress, out AOAddress);

    ushort data1 = slave.DataStore.HoldingRegisters[AOAddress];
    ushort data2 = slave.DataStore.HoldingRegisters[AOAddress + 1];
    ConcatNum(data1, data2, out data);
}

4.寄存器的数据都存储在PC端的DataStore中

5.Modbus Poll工具测试

  • 设置Connection-Connection Setup,根据上面设置RTU连接方式,Modbus Poll设置如下:(Slave设置的串口参数必须如下的配置相同

C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用_第5张图片

  • 设置Setup-Read/Write definition,SlaveID需要跟Slave从站设置相同,Scan Rate:间隔时间

C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用_第6张图片

  •  修改寄存器内的值,双击该寄存器的地址

C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用_第7张图片

  • 点击Send按钮后,会自动触发Slave的Modbus_DataStoreWriteTo方法,修改DataStore内的值

需安装vspd虚拟串口工具。通过工具添加COM1和COM2两个端口,进行以上测试

测试工具:https://download.csdn.net/download/lx_Angel/12981954

你可能感兴趣的:(Modbus)