1. 功能码列表:
0x01 读线圈状态(Read Coils)
0x02 读离散输入状态(Read Discrete Inputs )
0x03 读保持寄存器(Read Holding Registers )
0x04 读输入寄存器(Read Input Registers)
0x05 写单线圈(Write Single Coil )
0x06 写单寄存器(Write Single Register)
0x07 读取异常状态(限串行线)(Read Exception Status (Serial Line only) )
0x08 通信系统诊断(限串行线)(Diagnostics (Serial Line only) )
0x09-0x0A无
0x0B 获取串行通信事件计数器(Get Comm Event Counter (Serial Line only) )
0x0C 获取串行通信事件日志 ( Get Comm Event Log (Serial Line only) )
0x0D-0x0E无
0x0F 写多个线圈(Write Multiple Coils)
0x10 写多个寄存器(Write Multiple registers)
0x11 报告服务器ID(仅串行线)(Report Server ID (Serial Line only) )
0x12-0x13无
0x14 读文件记录(Read File Record )
0x15 写文件记录(Write File Record)
0x16 带屏蔽字写入寄存器(Mask Write Register )
0x17 读/写多个寄存器(Read/Write Multiple registers)
0x18 读取先进先出(FIFO)队列(Read FIFO Queue)
0x19-0x2A无
0x2B 封装接口传输(Encapsulated Interface Transport .)
2. 分主站,从站,主站是客户端,从站是服务端。启动时先启动从站(服务端),然后主站再连上从站,获取信息。
3. Device and Modbus 地址表(最大地址看设备)
| Device address | Modbus address | Description | Function | R/W | Comments |
| 1...10000 | address-1 | Coils(outputs) | 01 | Read/Write | 05 and 15 |
| 10001...20000 | address-10001 | Discrete Inputs | 02 | Read | |
| 40001...50000 | address-40001 | Holding Registers | 03 | Read/Write | 06,16,22 and 23 |
| 30001...40000 | address-30001 | Input Registers | 04 | Read |
4. 用C#做了一个小工具,用作Modbus TCP 学习的总结,链接见:https://download.csdn.net/download/garyaofq/88396590

界面左侧启动从站(自动门),右侧启动主站(RDS控制系统),启动3秒后锁定地址和端口。在右侧界面可以读,写线圈和寄存器。同时实时显示地址0-9的值。 帮助和左侧窗口显示功能码说明。
C#代码,引用EasyModbus,下面是详细的代码:
- /*
- * Created by SharpDevelop.
- * User: yaof
- * Date: 2023/10/3
- * Time: 19:19
- *
- * To change this template use Tools | Options | Coding | Edit Standard Headers.
- */
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- using EasyModbus;
-
- namespace Modbus_Slave
- {
- ///
- /// Description of MainForm.
- ///
- public partial class MainForm : Form
- {
- EasyModbus.ModbusServer modbusServer=null;
- System.Data.DataTable dt=new System.Data.DataTable ();
- System.Threading.Thread th;
-
- System.Threading.Thread thc;
- System.Threading.Thread thcc;
- EasyModbus.ModbusClient Master = null;
-
- public MainForm()
- {
- //
- // The InitializeComponent() call is required for Windows Forms designer support.
- //
- InitializeComponent();
- thcc=new System.Threading.Thread (new System.Threading.ThreadStart(counterclock));
-
- //创建一个服务,作为从站设备,等待主站查询或设置
- //从站可以不设置IP
- modbusServer = new ModbusServer();
- th=new System.Threading.Thread (new System.Threading.ThreadStart(monitor));
-
- System.Data.DataColumn dc=new System.Data.DataColumn ("address");
- dt.Columns.Add(dc);
- dc=new System.Data.DataColumn ("value");
- dt.Columns.Add(dc);
- for(var m=0;m<10;m++)
- {
- System.Data.DataRow dr=dt.NewRow();
- dr[0]=m.ToString();
- dr[1]="0";
- dt.Rows.Add(dr);
- }
-
- dataGridView1 .DataSource=dt;
- dataGridView1.Columns[0].Width=50;
- dataGridView1 .Columns[1].Width=50;
- dataGridView1 .ScrollBars=ScrollBars.None;
- //
- // TODO: Add constructor code after the InitializeComponent() call.
- //
- this.Master = new ModbusClient();
- this.slaveIP.Text = "127.0.0.1";
- this.slavePort.Text = "502";
- this.SlaveAddress.Text="1";
- var slaveid=int.Parse(this.SlaveAddress.Text);
- byte[] bytes = BitConverter.GetBytes(slaveid);//将int32转换为字节数组
- Master.UnitIdentifier =bytes[0];
- thc=new System.Threading.Thread (new System.Threading.ThreadStart(connectequipment));
-
- string bodystr="
Device and Modbus address ranges
"; - bodystr+="
Device address Modbus address Description Function R/W Comments ";- bodystr+="
1...10000 address-1 Coils(outputs) 01 Read/Write 05 and 15 "; - bodystr+="
10001...20000 address-10001 Discrete Inputs 02 Read "; - bodystr+="
40001...50000 address-40001 Holding Registers 03 Read/Write 06,16,22 and 23 "; - bodystr+="
30001...40000 address-30001 Input Registers 04 Read "; - bodystr+="
"; - webBrowser1.DocumentText=bodystr;
- button3.BackColor =Color.Red;
- button5.BackColor =Color.Red;
- button6.BackColor =Color.Red;
- button3.Enabled =true;
- button5.Enabled =true;
- button6.Enabled =true;
- }
-
- private bool UpdateCoil(int modbusaddress,int mvalue)
- {
- var slaveid=int.Parse(this.SlaveAddress.Text);
- byte[] bytes = BitConverter.GetBytes(slaveid);//将int32转换为字节数组
- modbusServer.UnitIdentifier=bytes[0];
- try
- {
- Master.WriteSingleCoil(modbusaddress, mvalue==1?true:false);
- }
- catch
- {
- return false;
- }
- return true;
- }
-
- private void UpdateRegister(int modbusaddress,int mvalue)
- {
- var slaveid=int.Parse(this.SlaveAddress.Text);
- byte[] bytes = BitConverter.GetBytes(slaveid);//将int32转换为字节数组
- modbusServer.UnitIdentifier=bytes[0];
- Master.WriteSingleRegister(modbusaddress,mvalue);
- }
-
- public void counterclock()
- {
- for(var m=3;m>=0;m--)
- {
- if(counter.InvokeRequired)
- {
- counter.Invoke(new Action(()=>{
- counter.Text=m.ToString();
- }));
- }else
- {
- counter.Text=m.ToString();
- }
- System.Threading .SpinWait.SpinUntil(() => false, 1000);
- //System.Threading .Thread.Sleep(1000);
- }
- }
-
- public void connectequipment()
- {
- //延时9秒启动服务,在此期间可以设置端口
- System.Threading .Thread.Sleep(3000);
- var SlaveIP="";
- var SlavePort="";
-
- if(slaveIP.InvokeRequired)
- {
- slaveIP.Invoke(new Action(()=>{
- SlaveIP =slaveIP.Text;
- slaveIP.Enabled=false;
- }));
- }else
- {
- SlaveIP =slaveIP.Text;
- slaveIP.Enabled=false;
- }
- if(slavePort.InvokeRequired)
- {
- slavePort.Invoke(new Action(()=>{
- SlavePort =slavePort.Text;
- slavePort.Enabled=false;
- }));
- }else
- {
- SlavePort =slavePort.Text;
- slavePort.Enabled=false;
- }
- Master.Connect(this.slaveIP.Text, int.Parse(this.slavePort.Text));
- }
- public void monitor()
- {
- //延时9秒启动服务,在此期间可以设置端口
- System.Threading .Thread.Sleep(3000);
- if(serverPort.InvokeRequired)
- {
- serverPort.Invoke(new Action(()=>{
- serverPort.Enabled =false;
- modbusServer.Port=int.Parse(this.serverPort.Text);
- }));
- }else
- {
- serverPort.Enabled =false;
- modbusServer.Port=int.Parse(this.serverPort.Text);
- }
-
- modbusServer.Listen();
- while(true)
- {
- //主站监控
- if(Master.Connected)
- {
- bool[] coilvalue=Master.ReadCoils(0,10);
- for(var m=0;m<10;m++)
- {
- System.Data.DataRow dr=dt.Rows[m];
- dr[0]=m;
- dr[1]=coilvalue[(m)% 10000]==true?1:0;
- }
-
- }
- System.Threading .Thread.Sleep(500);
- }
- }
-
- void Button2Click(object sender, EventArgs e)
- {
- if(comboBox1.SelectedItem.ToString()=="05")
- {
- UpdateCoil(int.Parse(address.Text),int.Parse(value.Text));
- }else if(comboBox1.SelectedItem.ToString()=="06")
- {
- UpdateRegister(40000+int.Parse(address.Text),int.Parse(value.Text));
- }
- }
-
- void MainFormFormClosing(object sender, FormClosingEventArgs e)
- {
- th.Abort();
- Master.Disconnect();
- }
- void HelpToolStripMenuItemClick(object sender, EventArgs e)
- {
- string funstr="Function 01 (01hex) Read Coils\r\n";
- funstr+="Function 02(02hex) Read Discrete Inputs\r\n";
- funstr+="Function 03 (03hex) Read Holding Registers\r\n";
- funstr+="Function 04 (04hex) Read Input Registers\r\n";
- funstr+="Function 05 (05hex) Write Single Coil\r\n";
- funstr+="Function 06 (06hex) Write Single Register\r\n";
- funstr+="Function 15 (0Fhex) Write Multiple Coils\r\n";
- funstr+="Function 16 (10hex) Write Multiple Registers\r\n";
- MessageBox.Show(funstr);
- }
- void Button1Click(object sender, EventArgs e)
- {
- var slaveid=int.Parse(this.SlaveAddress.Text);
- byte[] bytes = BitConverter.GetBytes(slaveid);//将int32转换为字节数组
- modbusServer.UnitIdentifier=bytes[0];
- try
- {
- if(comboBox2.SelectedItem.ToString()=="01")
- {
- bool[] coilstatus=Master.ReadCoils(int.Parse(saddress.Text),1);
- svalue.Text=coilstatus[0]==true?"1":"0";
- }else if(comboBox2.SelectedItem.ToString()=="02")
- {
- bool[] coilstatus=Master.ReadDiscreteInputs(10000+int.Parse(saddress.Text),1);
- svalue.Text=coilstatus[0]==true?"1":"0";
- }else if(comboBox2.SelectedItem.ToString()=="03")
- {
- int[] coilstatus=Master.ReadHoldingRegisters(40000+int.Parse(saddress.Text),1);
- svalue.Text=coilstatus[0].ToString();
- }else if(comboBox2.SelectedItem.ToString()=="04")
- {
- int[] coilstatus=Master.ReadInputRegisters(30000+int.Parse(saddress.Text),1);
- svalue.Text=coilstatus[0].ToString();
- }
- }
- catch
- {
-
- }
- }
- void Button3Click(object sender, EventArgs e)
- {
- thcc.Start();
- th.Start();
- thc.Start();
- button3.BackColor =Color.Green;
- button5.BackColor =Color.Gray;
- button6.BackColor =Color.Gray;
- button5.Enabled =false;
- button6.Enabled =false;
- }
- void Button4Click(object sender, EventArgs e)
- {
- if(comboBox1.SelectedItem.ToString()=="05")
- {
- UpdateCoil(int.Parse(address.Text),1);
- }else if(comboBox1.SelectedItem.ToString()=="06")
- {
- UpdateRegister(40000+int.Parse(address.Text),1);
- }
- }
- void Button5Click(object sender, EventArgs e)
- {
- //仅启动从站
- thcc.Start();
- th.Start();
- button5.BackColor =Color.Green;
- button3.Enabled =false;
- button3.BackColor =Color.Gray;
- }
- void Button6Click(object sender, EventArgs e)
- {
- //仅启动主站
- thc.Start();
- button6.BackColor =Color.Green;
- }
- /**************************************************************************************
- * 0x01 读线圈状态(Read Coils)
- 0x02 读离散输入状态(Read Discrete Inputs )
- 0x03 读保持寄存器(Read Holding Registers )
- 0x04 读输入寄存器(Read Input Registers)
- 0x05 写单线圈(Write Single Coil )
- 0x06 写单寄存器(Write Single Register)
- 0x07 读取异常状态(限串行线)(Read Exception Status (Serial Line only) )
- 0x08 通信系统诊断(限串行线)(Diagnostics (Serial Line only) )
- 0x09-0x0A无
- 0x0B 获取串行通信事件计数器(Get Comm Event Counter (Serial Line only) )
- 0x0C 获取串行通信事件日志 ( Get Comm Event Log (Serial Line only) )
- 0x0D-0x0E无
- 0x0F 写多个线圈(Write Multiple Coils)
- 0x10 写多个寄存器(Write Multiple registers)
- 0x11 报告服务器ID(仅串行线)(Report Server ID (Serial Line only) )
- 0x12-0x13无
- 0x14 读文件记录(Read File Record )
- 0x15 写文件记录(Write File Record)
- 0x16 带屏蔽字写入寄存器(Mask Write Register )
- 0x17 读/写多个寄存器(Read/Write Multiple registers)
- 0x18 读取先进先出(FIFO)队列(Read FIFO Queue)
- 0x19-0x2A无
- 0x2B 封装接口传输(Encapsulated Interface Transport .)
- ********************************************************************************/
- }
-
- }