Modbus主机/从机模拟程序
Modbus poll 和Modbus slave是一组Modbus仿真软件,可以实现Modbus RTU、TCP、串口仿真等。
仿真软件网址:https://modbustools.com/download.html
在ModbusTCP中,Modbus poll 作为客户端请求数据,Modbus slave 作为服务器端处理请求。
使用c语言编写客户端连接Modbus slave时,注意数据格式,一条指令一次性发出,否则连接会出错。
使用软件时,需要指定功能码,在setup->slave definition或者poll definition中进行设置。
– slave ID:从站编号(事务标识符)
– function:功能码,0x01对应线圈操作,0x02对应离散量操作,0x03对应保持寄存器操作,0x04对应输入寄存器操作
– address:开始地址
– quantity:寄存器/线圈/离散量 的数量
使用步骤:
1、打开Modbus Slave进行连接,串口(Modbus RTU或Modbus ASCII协议)参考图1, TCP/IP协议参考图2
2、设置从站编号、功能码,根据需要调试的功能码修改
TCP/IP协议开发
public partial class Form2 : Form { Socket client; int len = 100; public Form2() { InitializeComponent(); #region //01 读线圈状态 //txtSend.Text = "00 01 00 00 00 06 01 01 00 00 00 0F"; //len = 9 + 2; // 9+ceil(数量/8) //00 01 00 00 00 05 01 01 02 69 73 //02 读输入离散量 //txtSend.Text = "00 01 00 00 00 06 01 02 00 00 00 12"; //len = 9 + 3; // 9+ceil(数量/8) //00 01 00 00 00 06 01 02 03 69 73 03 //03 读保持寄存器 //txtSend.Text = "00 01 00 00 00 06 01 03 00 00 00 03"; //len = 9+6; // 9+数量*2 //00 01 00 00 00 09 01 03 06 00 10 00 19 7F FF //04 读输入寄存器 //txtSend.Text = "00 01 00 00 00 06 01 04 00 00 00 03"; //len = 9+6; // 9+数量*2 //00 01 00 00 00 09 01 04 06 00 10 00 19 7F FF //05 写单个线圈 //txtSend.Text = "00 01 00 00 00 06 01 05 00 03 FF 00"; //len = 12; //00 01 00 00 00 06 01 05 00 03 FF 00 //06 写单个保持寄存器 //txtSend.Text = "00 01 00 00 00 06 01 06 00 00 00 0A"; //len = 12; //00 01 00 00 00 06 01 06 00 00 00 0A //0F 写多个线圈 //txtSend.Text = "00 01 00 00 00 09 01 0F 00 00 00 0A 02 13 01"; //len = 12; //00 01 00 00 00 06 01 0F 00 00 00 0A //10 写多个保持寄存器 //txtSend.Text = "00 01 00 00 00 0B 01 10 00 00 00 02 04 00 0F 10 10"; //len = 12; //00 01 00 00 00 06 01 10 00 00 00 02 #endregion } private void btnSend_Click(object sender, EventArgs e) { txtReceive.Text = ""; client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); client.Connect("127.0.0.1", 502); byte[] buffer = Hex2Byte(txtSend.Text); client.Send(buffer); buffer = new byte[len]; client.Receive(buffer); this.Invoke(() => { txtReceive.Text = Byte2Hex(buffer); }); client.Close(); } public String Byte2Hex(byte[] bytes) { return BitConverter.ToString(bytes).Replace('-', ' ').Trim(); } public byte[] Hex2Byte(String hex) { string[] temp = hex.Split(' '); byte[] b = new byte[temp.Length + 2]; for (int i = 0; i < temp.Length; i++) { b[i] = Convert.ToByte(temp[i], 16); } return b; }
RTU协议开发
public partial class Form3 : Form { private SerialPort spCOM1; public Form3() { InitializeComponent(); spCOM1 = new SerialPort(); spCOM1.DataReceived += SpCOM1_DataReceived; } private void SpCOM1_DataReceived(object sender, SerialDataReceivedEventArgs e) { byte[] buffer = new byte[spCOM1.BytesToRead]; spCOM1.Read(buffer, 0, buffer.Length); string data = ToHex(buffer); this.Invoke(() => { txtReceive.Text += data + "\r\n"; }); } private void btnSend_Click(object sender, EventArgs e) { if (!spCOM1.IsOpen) { spCOM1.PortName = "COM1"; spCOM1.BaudRate = 9600; spCOM1.DataBits = 8; spCOM1.StopBits = StopBits.One; spCOM1.Parity = Parity.None; spCOM1.Open(); } else { string crc = CRCCheck(txtSend.Text); byte[] buffer = ToBytes(txtSend.Text + " " + crc); spCOM1.Write(buffer, 0, buffer.Length); } } /// <summary> /// CRC校验码 /// </summary> /// <param name="val"></param> /// <returns></returns> public string CRCCheck(string val) { val = val.TrimEnd(' '); string[] spva = val.Split(' '); byte[] bufData = new byte[spva.Length + 2]; bufData = ToBytesCRC(val); ushort CRC = 0xffff; ushort POLYNOMIAL = 0xa001; for (int i = 0; i < bufData.Length - 2; i++) { CRC ^= bufData[i]; for (int j = 0; j < 8; j++) { if ((CRC & 0x0001) != 0) { CRC >>= 1; CRC ^= POLYNOMIAL; } else { CRC >>= 1; } } } return ToHex(System.BitConverter.GetBytes(CRC)); } public static byte[] ToBytesCRC(string hex) { string[] temp = hex.Split(' '); byte[] b = new byte[temp.Length + 2]; for (int i = 0; i < temp.Length; i++) { b[i] = Convert.ToByte(temp[i], 16); } return b; } public static String ToHex(byte[] vars) { return BitConverter.ToString(vars).Replace('-', ' ').Trim(); } public static byte[] ToBytes(string hex) { string[] temp = hex.Split(' '); byte[] b = new byte[temp.Length]; for (int i = 0; i < temp.Length; i++) { if (temp[i].Length > 0) b[i] = Convert.ToByte(temp[i], 16); } return b; } }
标签:00,01,06,C#,Text,Modbus,开发,byte From: https://www.cnblogs.com/xesx/p/17727390.html