抖音粉丝群1
『7x24小时有问必答』

前言
在工业自动化和数据采集领域,MODBUS TCP 协议因其简单易用和广泛支持而被广泛应用。C# 作为一种编程语言,结合 NModbus 库,可以高效地实现与 MODBUS 设备的通信。
本文将详细介绍如何使用 C# 和 NModbus 库来实现 MODBUS TCP 协议下的字符串和浮点数的读写操作。
通过本文,能够掌握如何在实际项目中集成这些功能,提高数据处理的效率和准确性。
引用NModbus
在NuGet搜索NModbus,添加引用。
1.png
封装ModbusTcp类
public class ModbusTCP

{

    private ModbusFactory modbusFactory;

    private IModbusMaster master;

    private TcpClient tcpClient;

    public string IPAdress { getset; }

    public int Port { getset; }

    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
设置
2.png
3.png
连接
private ModbusTCP modbus;

private void ConnectExecute()

{

   try

   {

      modbus = new ModbusTCP(IP, Port);

      pollingTimer.Start();

   }

   catch (Exception ex)

   {

      Msg.Info(ex.Message);

   }}
4.png
写入测试
NModbus提供的对寄存器读写方法,只包括ushort类型,需要对ushort进行进行转换。
封装转换类型
public class MODBUS

{

    /// 

    /// 赋值string

    /// 

    /// 

    /// 

    /// 

    /// 

    public static void SetString(ushort[] src, int start, string value)

    {

        byte[] bytesTemp = Encoding.UTF8.GetBytes(value);

        ushort[] dest = Bytes2Ushorts(bytesTemp);

        dest.CopyTo(src, start);

    }

    /// 

    /// 获取string

    /// 

    /// 

    /// 

    /// 

    /// 

    public static string GetString(ushort[] src, int start, int len)

    {

        ushort[] temp = new ushort[len];

        for (int i = 0; i < len; i++)

        {

            temp = src[i + start];

        }

        byte[] bytesTemp = Ushorts2Bytes(temp);

        string res = Encoding.UTF8.GetString(bytesTemp).Trim(new char[] { '\0' });

        return res;

    }

    /// 

    /// 赋值Real类型数据

    /// 

    /// 

    /// 

    /// 

    public static void SetReal(ushort[] src, int start, float value)

    {

        byte[] bytes = BitConverter.GetBytes(value);

        ushort[] dest = Bytes2Ushorts(bytes);

        dest.CopyTo(src, start);

    }

    /// 

    /// 获取float类型数据

    /// 

    /// 

    /// 

    /// 

    public static float GetReal(ushort[] src, int start)

    {

        ushort[] temp = new ushort[2];

        for (int i = 0; i < 2; i++)

        {

            temp = src[i + start];

        }

        byte[] bytesTemp = Ushorts2Bytes(temp);

        float res = BitConverter.ToSingle(bytesTemp, 0);

        return res;

    }

    /// 

    /// 赋值Short类型数据

    /// 

    /// 

    /// 

    /// 

    public static void SetShort(ushort[] src, int start, short value)

    {

        byte[] bytes = BitConverter.GetBytes(value);

        ushort[] dest = Bytes2Ushorts(bytes);

        dest.CopyTo(src, start);

    }

    /// 

    /// 获取short类型数据

    /// 

    /// 

    /// 

    /// 

    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 = 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 & 1) == 1;//判定byte的最后一位是否为1,若为1,则是true;否则是false

                b = (byte)(b >> 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)

                {

                    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 = (ushort)(srcPlus[i * 2] << 8 | srcPlus[2 * i + 1] & 0xff);

            }

        }

        else

        {

            for (int i = 0; i < count; i++)

            {

                dest = (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 >> 8);

                dest[i * 2 + 1] = (byte)(src >> 0);

            }

        }

        else

        {

            for (int i = 0; i < count; i++)

            {

                dest[i * 2] = (byte)(src >> 0);

                dest[i * 2 + 1] = (byte)(src >> 8);

            }

        }

        return dest;

    }

}

根据选择的类型写入
5.png
6.png
private void WriteExecute()

{

    try

    {

        if(VariableType == "real")

        {

            ushort[] buff = new ushort[2];

            float value = float.Parse(WriteValue);

            MODBUS.SetReal(buff, 0value);

            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, 0value);

            modbus.WriteMultipleRegisters(SlaveID, WriteAddress, buff);

        }

    }

    catch (Exception ex)

    {

        Msg.Info(ex.Message);

    }}
7.png
可以看到ModbusSlave上面的数据,一个浮点型数据占用两个寄存器,4个byte。按照下图设置后,可以看到,已经写入成功。
8.png
读取测试
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, 010); 

        }

        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);

    }}
9.png
字符串写入和读取
参照VariableType=="string"部分代码。
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
作者:Samberger
出处:cnblogs.com/Samberger/p/13039429.html
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!

END

方便大家交流、资源共享和共同成长
纯技术交流群,需要加入的小伙伴请扫码,并备注加群
10.png

推荐阅读

觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力

11.gif
收藏
12.gif
点赞
13.gif
分享
14.gif
在看

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码