欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-14 09:31:37
...

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工具的使用

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

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

  • 配置完成后点击连接C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用,连接成功后的状态如下:

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

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

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

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<ModbusSlaveRequestEventArgs>(Modbus_Request_Event);
slave.DataStore = Modbus.Data.DataStoreFactory.CreateDefaultDataStore();
slave.DataStore.DataStoreWrittenTo += new EventHandler<DataStoreEventArgs>(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工具的使用

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

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

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

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

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

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

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

相关标签: Modbus