用NModbus4 实现Modbus服务器端(从站,Slave,有源码地址)

我们做上位机除了读取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

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潘诺西亚的火山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值