C#基於NModbus實現MODBUSTCP字元串、浮點數讀寫

来源:https://www.cnblogs.com/Samberger/archive/2020/06/03/13039429.html
-Advertisement-
Play Games

引用NModbus 在NuGet搜索NModbus,添加引用。 封裝ModbusTcp類 public class ModbusTCP { private ModbusFactory modbusFactory; private IModbusMaster master; private TcpCl ...


引用NModbus

在NuGet搜索NModbus,添加引用。

封裝ModbusTcp類

    public class ModbusTCP
    {
        private ModbusFactory modbusFactory;
        private IModbusMaster master;
        private TcpClient tcpClient;

        public string IPAdress { get; set; }
        public int Port { get; set; }

        public bool Connected
        {
            get => tcpClient.Connected;
        }

        public ModbusTCP(string ip, int port)
        {
            IPAdress = ip;
            Port = port;

            modbusFactory = new ModbusFactory();
            tcpClient = new TcpClient(IPAdress, Port);
            master = modbusFactory.CreateMaster(tcpClient);
            master.Transport.ReadTimeout = 2000;
            master.Transport.Retries = 10;
        }


        public bool[] ReadCoils(byte slaveAddress, ushort startAddress, ushort num)
        {
            return master.ReadCoils(slaveAddress, startAddress, num);
        }

        public bool[] ReadInputs(byte slaveAddress, ushort startAddress, ushort num)
        {
            return master.ReadInputs(slaveAddress, startAddress, num);
        }

        public ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort num)
        {
            return master.ReadHoldingRegisters(slaveAddress, startAddress, num);
        }

        public ushort[] ReadInputRegisters(byte slaveAddress, ushort startAddress, ushort num)
        {
            return master.ReadInputRegisters(slaveAddress, startAddress, num);
        }

        public void WriteSingleCoil(byte slaveAddress, ushort startAddress, bool value)
        {
            master.WriteSingleCoil(slaveAddress, startAddress, value);
        }

        public void WriteSingleRegister(byte slaveAddress, ushort startAddress, ushort value)
        {
            master.WriteSingleRegister(slaveAddress, startAddress, value);
        }

        public void WriteMultipleCoils(byte slaveAddress, ushort startAddress, bool[] value)
        {
            master.WriteMultipleCoils(slaveAddress, startAddress, value);
        }

        public void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] value)
        {
            master.WriteMultipleRegisters(slaveAddress, startAddress, value);
        }

    }

連接測試

下載 Modbus Slave
鏈接:https://pan.baidu.com/s/1ydX_9KElkOTA7h-E3SIadw
提取碼:7fh5
設置

連接

      private ModbusTCP modbus;
      private void ConnectExecute()
      {
         try
         {
            modbus = new ModbusTCP(IP, Port);
            pollingTimer.Start();
         }
         catch (Exception ex)
         {
            Msg.Info(ex.Message);
         }
      }

寫入測試

NModbus提供的對寄存器讀寫方法,只包括ushort類型,需要對ushort進行進行轉換。
封裝轉換類型

    public class MODBUS
    {
        /// <summary>
        /// 賦值string
        /// </summary>
        /// <param name="src"></param>
        /// <param name="start"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static void SetString(ushort[] src, int start, string value)
        {
            byte[] bytesTemp = Encoding.UTF8.GetBytes(value);
            ushort[] dest = Bytes2Ushorts(bytesTemp);
            dest.CopyTo(src, start);
        }

        /// <summary>
        /// 獲取string
        /// </summary>
        /// <param name="src"></param>
        /// <param name="start"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public static string GetString(ushort[] src, int start, int len)
        {
            ushort[] temp = new ushort[len];
            for (int i = 0; i < len; i++)
            {
                temp[i] = src[i + start];
            }
            byte[] bytesTemp = Ushorts2Bytes(temp);
            string res = Encoding.UTF8.GetString(bytesTemp).Trim(new char[] { '\0' });
            return res;
        }

        /// <summary>
        /// 賦值Real類型數據
        /// </summary>
        /// <param name="src"></param>
        /// <param name="start"></param>
        /// <param name="value"></param>
        public static void SetReal(ushort[] src, int start, float value)
        {
            byte[] bytes = BitConverter.GetBytes(value);

            ushort[] dest = Bytes2Ushorts(bytes);

            dest.CopyTo(src, start);
        }

        /// <summary>
        /// 獲取float類型數據
        /// </summary>
        /// <param name="src"></param>
        /// <param name="start"></param>
        /// <returns></returns>
        public static float GetReal(ushort[] src, int start)
        {
            ushort[] temp = new ushort[2];
            for (int i = 0; i < 2; i++)
            {
                temp[i] = src[i + start];
            }
            byte[] bytesTemp = Ushorts2Bytes(temp);
            float res = BitConverter.ToSingle(bytesTemp, 0);
            return res;
        }

        /// <summary>
        /// 賦值Short類型數據
        /// </summary>
        /// <param name="src"></param>
        /// <param name="start"></param>
        /// <param name="value"></param>
        public static void SetShort(ushort[] src, int start, short value)
        {
            byte[] bytes = BitConverter.GetBytes(value);

            ushort[] dest = Bytes2Ushorts(bytes);

            dest.CopyTo(src, start);
        }

        /// <summary>
        /// 獲取short類型數據
        /// </summary>
        /// <param name="src"></param>
        /// <param name="start"></param>
        /// <returns></returns>
        public static short GetShort(ushort[] src, int start)
        {
            ushort[] temp = new ushort[1];
            temp[0] = src[start];
            byte[] bytesTemp = Ushorts2Bytes(temp);
            short res = BitConverter.ToInt16(bytesTemp, 0);
            return res;
        }


        public static bool[] GetBools(ushort[] src, int start, int num)
        {
            ushort[] temp = new ushort[num];
            for (int i = start; i < start + num; i++)
            {
                temp[i] = src[i + start];
            }
            byte[] bytes = Ushorts2Bytes(temp);

            bool[] res = Bytes2Bools(bytes);

            return res;
        }

        private static bool[] Bytes2Bools(byte[] b)
        {
            bool[] array = new bool[8*b.Length];

            for (int i = 0; i < b.Length; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    array[i * 8 + j] = (b[i] & 1) == 1;//判定byte的最後一位是否為1,若為1,則是true;否則是false
                    b[i] = (byte)(b[i] >> 1);//將byte右移一位
                }
            }
            return array;
        }

        private static byte Bools2Byte(bool[] array)
        {
            if (array != null && array.Length > 0)
            {
                byte b = 0;
                for (int i = 0; i < 8; i++)
                {
                    if (array[i])
                    {
                        byte nn = (byte)(1 << i);//左移一位,相當於×2
                        b += nn;
                    }
                }
                return b;
            }
            return 0;
        }

        private static ushort[] Bytes2Ushorts(byte[] src, bool reverse = false)
        {
            int len = src.Length;

            byte[] srcPlus = new byte[len + 1];
            src.CopyTo(srcPlus, 0);
            int count = len >> 1;

            if (len % 2 != 0)
            {
                count += 1;
            }

            ushort[] dest = new ushort[count];
            if(reverse)
            {
                for (int i = 0; i < count; i++)
                {
                    dest[i] = (ushort)(srcPlus[i * 2] << 8 | srcPlus[2 * i + 1] & 0xff);
                }
            }
            else
            {
                for (int i = 0; i < count; i++)
                {
                    dest[i] = (ushort)(srcPlus[i * 2] & 0xff | srcPlus[2 * i + 1] << 8 );
                }
            }
         
            return dest;
        }

        private static byte[] Ushorts2Bytes(ushort[] src, bool reverse = false)
        {

            int count = src.Length;
            byte[] dest = new byte[count << 1];
            if(reverse)
            {
                for (int i = 0; i < count; i++)
                {
                    dest[i * 2] = (byte)(src[i] >> 8);
                    dest[i * 2 + 1] = (byte)(src[i] >> 0);
                }
            }
            else
            {
                for (int i = 0; i < count; i++)
                {
                    dest[i * 2] = (byte)(src[i] >> 0);
                    dest[i * 2 + 1] = (byte)(src[i] >> 8);
                }
            }
            return dest;
        }
    }

根據選擇的類型寫入

        private void WriteExecute()
        {
            try
            {
                if(VariableType == "real")
                {
                    ushort[] buff = new ushort[2];
                    float value = float.Parse(WriteValue);
                    MODBUS.SetReal(buff, 0, value);
                    modbus.WriteMultipleRegisters(SlaveID, WriteAddress, buff);
                }
                else if(VariableType == "string")
                {
                    ushort[] buff = new ushort[10];
                    MODBUS.SetString(buff, 0, WriteValue);
                    modbus.WriteMultipleRegisters(SlaveID, WriteAddress, buff);
                }
                else if(VariableType == "Int16")
                {
                    ushort[] buff = new ushort[1];
                    short value = short.Parse(WriteValue);
                    MODBUS.SetShort(buff, 0, value);
                    modbus.WriteMultipleRegisters(SlaveID, WriteAddress, buff);
                }
            }
            catch (Exception ex)
            {
                Msg.Info(ex.Message);
            }
        }


可以看到ModbusSlave上面的數據,一個浮點型數據占用兩個寄存器,4個byte。按照下圖設置後,可以看到,已經寫入成功。

讀取測試

        private void ReadExecute()
        {
            try
            {
                if (VariableType == "real")
                {
                    ushort[] buff = modbus.ReadHoldingRegisters(SlaveID, ReadAddress, 2);
                    float value = MODBUS.GetReal(buff, 0);
                    ReadValue = value.ToString();
                }
                else if(VariableType == "string")
                {
                    ushort[] buff = modbus.ReadHoldingRegisters(SlaveID, ReadAddress, 10);
                    ReadValue = MODBUS.GetString(buff, 0, 10); 
                }
                else if(VariableType == "Int16")
                {
                    ushort[] buff = modbus.ReadHoldingRegisters(SlaveID, ReadAddress, 1);
                    short value = MODBUS.GetShort(buff, 0);
                    ReadValue = value.ToString();
                }
            }
            catch (Exception ex)
            {
                Msg.Info(ex.Message);
            }
        }

字元串寫入和讀取

參照VariableType=="string"部分代碼。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在寫代碼的時候,免不了要使用變數。但程式中的一個變數並不一定是在哪裡都可以被使用,根據情況不同,會有不同的“有效範圍”。 看這樣一段代碼: def func(x): print ('X in the beginning of func(x): ', x) x = 2 print ('X in the ...
  • 一.瀏覽器內核太撈了一般人都會避開他 from selenium.webdriver import Chrome from selenium.webdriver import ChromeOptions option = ChromeOptions() option.add_experimental ...
  • spring註入map,spring註入一個介面的多個實現類在map里 ...
  • 轉載https://www.jianshu.com/p/5d27888e7c93#!/xh #!/usr/bin/env python # -*- coding=utf-8 -*- """ AES加密解密工具類 @author jzx @date 2018/10/24 此工具類加密解密結果與 htt ...
  • 什麼是sam 轉換 Single Abstract Method 實際上這是java8中提出的概念,你就把他理解為是一個方法的介面的就可以了 看一下我們每天都在使用的線程池 ExecutorService executorService= Executors.newScheduledThreadPo ...
  • 結合 AOP 輕鬆處理事件發佈處理日誌 Intro 前段時間,實現了 EventBus 以及 EventQueue 基於 Event 的事件處理,但是沒有做日誌(EventLog)相關的部分,原本想增加兩個介面, 處理事件發佈日誌和事件處理日誌,最近用了 AOP 的思想處理了 EntityFrame ...
  • Microsoft.AspNetCore.Mvc.Versioning //引入程式集 .net core 下麵api的版本控製作用不需要多說,可以查閱https://www.cnblogs.com/dc20181010/p/11313738.html 普通的版本控制一般是通過鏈接、header此類 ...
  • 系列文章 基於 abp vNext 和 .NET Core 開發博客項目 - 使用 abp cli 搭建項目 基於 abp vNext 和 .NET Core 開發博客項目 - 給項目瘦身,讓它跑起來 基於 abp vNext 和 .NET Core 開發博客項目 - 完善與美化,Swagger登場 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...