C# NModubs的简单应用
一、ModbusTcp协议
ModBus Tcp是基于TCP/IP的报文协议,采用主\从方式通信,但是主从之间的端口是固定的:502; ModBus地址:由5位数字组成(PS:40001-49999表示HoldingRegister),包括起始数据类型代号,以及后面的偏移地址
寄存器:
CiolRegister(线圈寄存器)占一个位Bit,数据范围0-1之间,在C#中表示一个Bool类型;
ps:可以用来做设备控制点位,以及状态字。
HoldingRegister(保持寄存器)占2个Byte,16Bit,数据范围:0-65535之间,在C#一个HR记作一个ushort,表示一个无符号(正数)16位整数;
二、主站
1、主站代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Modbus.Device;
using System.Net.Sockets;
using System.Net;
using Modbus.Data;
using Modbus.Utility;
namespace NModbus4_Pro.U_UserPage
{
public partial class UserModbusMaster : UserControl
{
public UserModbusMaster()
{
InitializeComponent();
}
private TcpClient client;
private ModbusIpMaster master;
private void ModbusSlave_Load(object sender, EventArgs e)
{
}
#region Control
private void SetDataCoil(bool[] coils)
{
foreach(Control c in groupBox1.Controls)
{
if (c.GetType() == typeof(CheckBox)&& c.Tag != null)
{
CheckBox ck = c as CheckBox;
int tag = Convert.ToInt32(c.Tag);
if (ck.InvokeRequired)
{
this.BeginInvoke(new Action(delegate
{
ck.Checked = coils[tag];
}));
}
else
{
ck.Checked = coils[tag];
}
}
}
}
private void SetDataHoldingRegister(ushort[] holding_register)
{
foreach (Control c in groupBox2.Controls)
{
if (c.GetType() == typeof(TextBox) && c.Tag != null)
{
TextBox txtBox = c as TextBox;
int tag = Convert.ToInt32(c.Tag);
if (txtBox.InvokeRequired)
{
this.BeginInvoke(new Action(delegate
{
txtBox.Text = holding_register[tag-1].ToString();
}));
}
else
{
txtBox.Text = holding_register[tag-1].ToString();
}
}
}
}
#endregion
private void btnStart_Click(object sender, EventArgs e)
{
try
{
this.Close();
client = new TcpClient();
client.Connect(IPAddress.Parse(txtIP.Text.Trim()), (int)txtPort.Value);
master = ModbusIpMaster.CreateIp(client);
if (client.Connected)
{
btnMaster.BackColor = Color.Green;
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
private void Close()
{
try
{
if (client != null && master != null)
{
client.Close();
master.Dispose();
btnMaster.BackColor = Color.LightYellow;
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void btnWrite_Click(object sender, EventArgs e)
{
if(client!=null&& master != null)
{
if (client.Connected)
{
master.WriteSingleCoil((ushort)nud_MasterCoilAds.Value, nud_MasterCoilVal.Value == 1 ? true : false);
master.WriteSingleRegister((ushort)nud_MasterHRAds.Value, (ushort)nud_MasterHRVal.Value);
}
else
{
MessageBox.Show("连接已断开!");
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
try
{
if (client != null && master != null)
{
if (client.Connected)
{
bool[] coils = master.ReadCoils(1, 0, 9);
this.SetDataCoil(coils);
ushort[] holding_register = master.ReadHoldingRegisters(1, 0, 12);
this.SetDataHoldingRegister(holding_register);
}
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
2、写入或者读取浮点型
因为接收和写入的数据类型都是ushort类型,所以如果需要发送或者接收负数或者浮点型的话,需要将ushort[]和float类型做互转
//将接收到的ushort[]转换为float类型
private float GetFloatFormUshortArray(ushort[] val)
{
if (val != null && val.Length == 2)
{
List<byte> result = new List<byte>();
result.AddRange(BitConverter.GetBytes(val[0]));
result.AddRange(BitConverter.GetBytes(val[1]));
return BitConverter.ToSingle(result.ToArray(), 0);
}
else
{
return 0.0f;
}
}
//将float类型分解成两个ushort类型
public ushort[] SetValue32(float value)
{
ushort[] usResult = new ushort[2];
usResult[0] = BitConverter.ToUInt16(BitConverter.GetBytes(value), 0);//高位
usResult[1] = BitConverter.ToUInt16(BitConverter.GetBytes(value), 2);//低位
return usResult;
}
三、从站
1、从站代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Modbus.Device;
using System.Net.Sockets;
using System.Net;
using Modbus.Data;
using Modbus.Utility;
namespace NModbus4_Pro.U_UserPage
{
public partial class UserModbusMaster : UserControl
{
public UserModbusMaster()
{
InitializeComponent();
}
private TcpClient client;
private ModbusIpMaster master;
private void ModbusSlave_Load(object sender, EventArgs e)
{
}
#region Control
private void SetDataCoil(bool[] coils)
{
foreach(Control c in groupBox1.Controls)
{
if (c.GetType() == typeof(CheckBox)&& c.Tag != null)
{
CheckBox ck = c as CheckBox;
int tag = Convert.ToInt32(c.Tag);
if (ck.InvokeRequired)
{
this.BeginInvoke(new Action(delegate
{
ck.Checked = coils[tag];
}));
}
else
{
ck.Checked = coils[tag];
}
}
}
}
private void SetDataHoldingRegister(ushort[] holding_register)
{
foreach (Control c in groupBox2.Controls)
{
if (c.GetType() == typeof(TextBox) && c.Tag != null)
{
TextBox txtBox = c as TextBox;
int tag = Convert.ToInt32(c.Tag);
if (txtBox.InvokeRequired)
{
this.BeginInvoke(new Action(delegate
{
txtBox.Text = holding_register[tag-1].ToString();
}));
}
else
{
txtBox.Text = holding_register[tag-1].ToString();
}
}
}
}
#endregion
private void btnStart_Click(object sender, EventArgs e)
{
try
{
this.Close();
client = new TcpClient();
client.Connect(IPAddress.Parse(txtIP.Text.Trim()), (int)txtPort.Value);
master = ModbusIpMaster.CreateIp(client);
if (client.Connected)
{
btnMaster.BackColor = Color.Green;
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
private void Close()
{
try
{
if (client != null && master != null)
{
client.Close();
master.Dispose();
btnMaster.BackColor = Color.LightYellow;
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void btnWrite_Click(object sender, EventArgs e)
{
if(client!=null&& master != null)
{
if (client.Connected)
{
master.WriteSingleCoil((ushort)nud_MasterCoilAds.Value, nud_MasterCoilVal.Value == 1 ? true : false);
master.WriteSingleRegister((ushort)nud_MasterHRAds.Value, (ushort)nud_MasterHRVal.Value);
}
else
{
MessageBox.Show("连接已断开!");
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
try
{
if (client != null && master != null)
{
if (client.Connected)
{
bool[] coils = master.ReadCoils(1, 0, 9);
this.SetDataCoil(coils);
ushort[] holding_register = master.ReadHoldingRegisters(1, 0, 12);
this.SetDataHoldingRegister(holding_register);
}
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
四、小结
附上资源: https://download.csdn.net/download/qq_39052187/89549332