天天看點

c#實作Modbus Tcp服務端程式開發

作者:慕楓楓
工業軟體調試中往往會遇到需要與modbus tcp裝置進行通訊的情況,為減少程式設計中存在的Bug,通常我們需要對其進行簡單的模拟測試,便于縮短真機調試。

正常的幾種方法:

- 第一種方式,通過真實的裝置進行模拟,例如PLC等

但是這一方式,往往受制于PLC程式設計,PLC端需編寫完成相應的通訊子產品,且需配合PLC程式設計軟體手動模拟信号實作工業軟體測試,有部分位址還需由外部接線進行觸發,無法進行全部位址模拟。

- 第二種方式,通過市面上鎖提供的Modbus Tcp軟體進行模拟測試

c#實作Modbus Tcp服務端程式開發

該種方式雖然能滿足部分調試要求,但想找到一款比較全面的調試工具還是比較難的。有些調試工具無法同時滿足線圈、離散輸入、保持寄存器等位址的同時監控;有些調試工具隻支援線圈、保持寄存器的寫入操作;還有些調試工具對位址總數有一定限制,無法模拟全部位址效果。

  • 第三種方式,自己建立Modbus Tcp服務端

    由于工具是為自行開發,是以功能上相對市面上所提供的調試工具更加靈活與全面,最重要是設計出的調試工具更加符合自己的調試習慣。

關鍵代碼展示,程式使用C#進行開發

1、建立服務端監聽,啟動伺服器

try
            {
                IPAddress Ip;
                int Port;
                //擷取IP位址
                try
                {
                    Ip = IPAddress.Parse(this.txt_ip.Text);
                }
                catch
                {
                    MessageBox.Show("請輸入正确的IP位址!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                //擷取端口号
                try
                {
                    Port = Convert.ToInt32(this.txt_port.Text);
                }
                catch
                {
                    MessageBox.Show("請輸入正确的IP位址!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                System.Net.NetworkInformation.IPGlobalProperties iproperties = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties();
                IPEndPoint[] ipEndPoints = iproperties.GetActiveTcpListeners();
                foreach (var con in ipEndPoints)
                {
                    if (con.Port == Port)
                    {
                        MessageBox.Show("目前端口已被占用!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return;
                    }
                }
                //建立通訊
                _server = new TcpListener(Ip, Port);
                _server.Start();
                _slave = ModbusTcpSlave.CreateTcp(_deviceNo, _server);
                _slave.DataStore = _dataStore;
                _slave.ListenAsync();
                this.btn_start.Enabled = false;
                this.btn_stop.Enabled = true;
                this.tr_CoilDiscretes.Enabled = true;
                this.tr_InputDiscretes.Enabled = true;
                this.tr_HoldingRegisters.Enabled = true;
                this.tr_InputRegisters.Enabled = true;
            }
            catch (Exception r)
            {
                MessageBox.Show(r.Message.ToString(), "出錯", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
           

2、界面顯示

try
            {
                if (!this.dgv_CoilDiscretes.Focused)
                {
                    ModbusDataCollection<bool> data_CoilDiscretes = _dataStore.CoilDiscretes;
                    dt_Coil.Clear();
                    for (int i = i_startAddress_Coil; i < i_lenght_Coil; i++)
                    {
                        dt_Coil.Rows.Add(i - 1, data_CoilDiscretes[i]);
                    }
                    this.dgv_CoilDiscretes.DataSource = dt_Coil;
                }
            }
            catch (Exception r)
            {
                MessageBox.Show(r.Message.ToString(), "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
           

3、資料寫入

try
            {
                ushort address = Convert.ToUInt16(dt_Coil.Rows[e.RowIndex][0]);
                bool value = Convert.ToBoolean(dt_Coil.Rows[e.RowIndex][1]);
                _dataStore.CoilDiscretes[address + 1] = value;
                this.tr_CoilDiscretes.Enabled = true;
                this.gb1.Focus();
            }
            catch (Exception r)
            {
                MessageBox.Show(r.Message.ToString(), "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
           

程式界面展示

c#實作Modbus Tcp服務端程式開發

繼續閱讀