我们做上位机除了读取PLC,单片机的数据,也经常需要转发数据,将数据转发给BS应用等,这时候一个Modbus服务器就非常有必要了,它简单开源稳定,今天我就用C# 实现一个Modbus服务器
using Modbus.Data;
using Modbus.Device;
using System;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
namespace ModbusSlaveFrm
{
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
}
private TcpListener listener;
private ModbusSlave slave;
private void BtnConn_Click(object sender, EventArgs e)
{
try
{
listener = new TcpListener(IPAddress.Parse(textBox1.Text), int.Parse(textBox2.Text));
listener.Start();
slave = ModbusTcpSlave.CreateTcp(1, listener);
//创建寄存器存储对象
slave.DataStore = DataStoreFactory.CreateDefaultDataStore();
slave.DataStore.DataStoreWrittenTo += DataStore_DataStoreWrittenTo;
//slave.ModbusSlaveRequestReceived += Slave_ModbusSlaveRequestReceived; ;
slave.WriteComplete += Slave_WriteComplete; ;
slave.Listen();
BtnConn.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void Slave_WriteComplete(object sender, ModbusSlaveRequestEventArgs e)
{
if (richTextBox1.InvokeRequired)
{
this.BeginInvoke(new Action(delegate
{
richTextBox1.AppendText("[写入数据完成:]\r\n" + Newtonsoft.Json.JsonConvert.SerializeObject(e.Message) + "\r\n ******** \r\n \r\n");
}));
}
}
private void Slave_ModbusSlaveRequestReceived(object sender, ModbusSlaveRequestEventArgs e)
{
if (richTextBox1.InvokeRequired)
{
this.BeginInvoke(new Action(delegate
{
richTextBox1.AppendText("[收到数据:]\r\n" + Newtonsoft.Json.JsonConvert.SerializeObject(e.Message) + "\r\n ******** \r\n \r\n");
}));
}
}
private void DataStore_DataStoreWrittenTo(object sender, DataStoreEventArgs e)
{
switch (e.ModbusDataType)
{
case ModbusDataType.Coil: //code 5
ModbusDataCollection<bool> discretes = slave.DataStore.CoilDiscretes;
if (richTextBox1.InvokeRequired)
{
this.BeginInvoke(new Action(delegate
{
richTextBox1.AppendText("[ModbusDataType.Coil]\r\n" + Newtonsoft.Json.JsonConvert.SerializeObject(discretes) + "\r\n ******** \r\n \r\n");
}));
}
break;
case ModbusDataType.HoldingRegister: //code 15
ModbusDataCollection<ushort> holdingRegisters = slave.DataStore.HoldingRegisters;
if (richTextBox1.InvokeRequired)
{
this.BeginInvoke(new Action(delegate
{
richTextBox1.AppendText("[ModbusDataType.HoldingRegister]\r\n" + Newtonsoft.Json.JsonConvert.SerializeObject(holdingRegisters) + "\r\n ******** \r\n \r\n");
}));
}
break;
default:
if (richTextBox1.InvokeRequired)
{
this.BeginInvoke(new Action(delegate
{
richTextBox1.AppendText($"[{e.ModbusDataType}]\r\n" + Newtonsoft.Json.JsonConvert.SerializeObject(e.Data) + "\r\n ******** \r\n \r\n");
}));
}
break;
}
}
private void BtnDisc_Click(object sender, EventArgs e)
{
slave.Dispose();
BtnConn.Enabled = true;
}
private void BtnWrite_Click(object sender, EventArgs e)
{
//CoilDiscretes表示一个Bit,也就是一个bool类型
//master.WriteSingleCoil((ushort)cliAddress.Value ,cliValue.Value == 1 ? true : false);
//HoldingRegisters表示一个无符号的16位整数(2的16次幂:0-65535)
//CoilDiscretes表示一个Bit,也就是一个bool类型
//slave.DataStore.CoilDiscretes[(int)cliAddress.Value] = cliValue.Value == 1 ? true : false;
//HoldingRegisters表示一个无符号的16位整数(2的16次幂:0-65535)
//slave.DataStore.HoldingRegisters[(int)1] = (ushort)122;
slave.DataStore.HoldingRegisters[(int)1] = ushort.Parse(textBox3.Text);
slave.DataStore.HoldingRegisters[(int)2] = ushort.Parse(textBox4.Text);
slave.DataStore.HoldingRegisters[(int)3] = ushort.Parse(textBox5.Text);
}
}
}
用ModbusPoll测试:
效果:
觉得好用点个赞
GitHub地址:https://gitee.com/helodoger/my-csharp-code.git