首页 > 编程语言 >C# Modbus开发

C# Modbus开发

时间:2023-09-26 15:36:48浏览次数:31  
标签:00 01 06 C# Text Modbus 开发 byte

Modbus主机/从机模拟程序

Modbus poll 和Modbus slave是一组Modbus仿真软件,可以实现Modbus RTU、TCP、串口仿真等。
仿真软件网址:https://modbustools.com/download.html
在ModbusTCP中,Modbus poll 作为客户端请求数据,Modbus slave 作为服务器端处理请求。
使用c语言编写客户端连接Modbus slave时,注意数据格式,一条指令一次性发出,否则连接会出错。
使用软件时,需要指定功能码,在setup->slave definition或者poll definition中进行设置。
– slave ID:从站编号(事务标识符)
– function:功能码,0x01对应线圈操作,0x02对应离散量操作,0x03对应保持寄存器操作,0x04对应输入寄存器操作
– address:开始地址
– quantity:寄存器/线圈/离散量 的数量

 使用步骤:

1、打开Modbus Slave进行连接,串口(Modbus RTU或Modbus ASCII协议)参考图1, TCP/IP协议参考图2

2、设置从站编号、功能码,根据需要调试的功能码修改

 

TCP/IP协议开发

public partial class Form2 : Form
{
    Socket client;
    int len = 100; 

    public Form2()
    {
        InitializeComponent();

        #region
        //01 读线圈状态
        //txtSend.Text = "00 01 00 00 00 06 01 01 00 00 00 0F";
        //len = 9 + 2; // 9+ceil(数量/8)
        //00 01 00 00 00 05 01 01 02 69 73

        //02 读输入离散量
        //txtSend.Text = "00 01 00 00 00 06 01 02 00 00 00 12";
        //len = 9 + 3; // 9+ceil(数量/8)
        //00 01 00 00 00 06 01 02 03 69 73 03 

        //03 读保持寄存器
        //txtSend.Text = "00 01 00 00 00 06 01 03 00 00 00 03";
        //len = 9+6; // 9+数量*2
        //00 01 00 00 00 09 01 03 06 00 10 00 19 7F FF

        //04 读输入寄存器
        //txtSend.Text = "00 01 00 00 00 06 01 04 00 00 00 03";
        //len = 9+6; // 9+数量*2
        //00 01 00 00 00 09 01 04 06 00 10 00 19 7F FF

        //05 写单个线圈
        //txtSend.Text = "00 01 00 00 00 06 01 05 00 03 FF 00";
        //len = 12; 
        //00 01 00 00 00 06 01 05 00 03 FF 00

        //06 写单个保持寄存器
        //txtSend.Text = "00 01 00 00 00 06 01 06 00 00 00 0A";
        //len = 12; 
        //00 01 00 00 00 06 01 06 00 00 00 0A

        //0F 写多个线圈
        //txtSend.Text = "00 01 00 00 00 09 01 0F 00 00 00 0A 02 13 01";
        //len = 12; 
        //00 01 00 00 00 06 01 0F 00 00 00 0A

        //10 写多个保持寄存器
        //txtSend.Text = "00 01 00 00 00 0B 01 10 00 00 00 02 04 00 0F 10 10";
        //len = 12; 
        //00 01 00 00 00 06 01 10 00 00 00 02
        #endregion

    }

    private void btnSend_Click(object sender, EventArgs e)
    {
        txtReceive.Text = "";
        client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        client.Connect("127.0.0.1", 502);

        byte[] buffer = Hex2Byte(txtSend.Text);
        client.Send(buffer);

        buffer = new byte[len];
        client.Receive(buffer);
        this.Invoke(() =>
        {
            txtReceive.Text = Byte2Hex(buffer);
        });

        client.Close();
    }


    public String Byte2Hex(byte[] bytes)
    {
        return BitConverter.ToString(bytes).Replace('-', ' ').Trim();
    }

    public byte[] Hex2Byte(String hex)
    {
        string[] temp = hex.Split(' ');
        byte[] b = new byte[temp.Length + 2];

        for (int i = 0; i < temp.Length; i++)
        {
            b[i] = Convert.ToByte(temp[i], 16);
        }

        return b;
    }

 

 RTU协议开发

    public partial class Form3 : Form
    {

        private SerialPort spCOM1;

        public Form3()
        {
            InitializeComponent();

            spCOM1 = new SerialPort();
            spCOM1.DataReceived += SpCOM1_DataReceived;
        }

        private void SpCOM1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] buffer = new byte[spCOM1.BytesToRead];
            spCOM1.Read(buffer, 0, buffer.Length);
            string data = ToHex(buffer);
            this.Invoke(() =>
            {
                txtReceive.Text += data + "\r\n";
            });
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (!spCOM1.IsOpen)
            {
                spCOM1.PortName = "COM1";
                spCOM1.BaudRate = 9600;
                spCOM1.DataBits = 8;
                spCOM1.StopBits = StopBits.One;
                spCOM1.Parity = Parity.None;
                spCOM1.Open();
            }
            else
            {
                string crc = CRCCheck(txtSend.Text);
                byte[] buffer = ToBytes(txtSend.Text + " " + crc);
                spCOM1.Write(buffer, 0, buffer.Length);
            }

        }

        /// <summary>
        /// CRC校验码
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public string CRCCheck(string val)
        {
            val = val.TrimEnd(' ');
            string[] spva = val.Split(' ');
            byte[] bufData = new byte[spva.Length + 2];
            bufData = ToBytesCRC(val);
            ushort CRC = 0xffff;
            ushort POLYNOMIAL = 0xa001;
            for (int i = 0; i < bufData.Length - 2; i++)
            {
                CRC ^= bufData[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((CRC & 0x0001) != 0)
                    {
                        CRC >>= 1;
                        CRC ^= POLYNOMIAL;
                    }
                    else
                    {
                        CRC >>= 1;
                    }
                }
            }
            return ToHex(System.BitConverter.GetBytes(CRC));
        }


        public static byte[] ToBytesCRC(string hex)
        {
            string[] temp = hex.Split(' ');
            byte[] b = new byte[temp.Length + 2];

            for (int i = 0; i < temp.Length; i++)
            {
                b[i] = Convert.ToByte(temp[i], 16);
            }

            return b;
        }

        public static String ToHex(byte[] vars)
        {
            return BitConverter.ToString(vars).Replace('-', ' ').Trim();
        }

        public static byte[] ToBytes(string hex)
        {
            string[] temp = hex.Split(' ');
            byte[] b = new byte[temp.Length];

            for (int i = 0; i < temp.Length; i++)
            {
                if (temp[i].Length > 0)
                    b[i] = Convert.ToByte(temp[i], 16);
            }

            return b;
        }


    }

 

标签:00,01,06,C#,Text,Modbus,开发,byte
From: https://www.cnblogs.com/xesx/p/17727390.html

相关文章

  • CH9141基础应用篇
    原文链接:https://www.cnblogs.com/risc5-ble/p/16397743.htmlCH9141使用十分方便,是一款蓝牙串口透传芯片,无需二次开发,可以直接使用的,支持三种模式:从机模式,主机模式,广播模式。对于模块刚拿到手的小伙伴可以先接上这几根线:1.购买带底板的豪友们,使用杜邦线将模块与CH340连接(VCC,GN......
  • Modbus 协议简介
    Modbus协议简介Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议。通过此协议,控制器相互之间、或控制器经由网络(如以太网)可以和其它设备之间进行通信。Modbus协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。一般将主控设备方所使用的协议称为ModbusMaste......
  • CH573 CH579 CH582程序烧录讲解
    原文链接:https://www.cnblogs.com/risc5-ble/p/16865626.html 第一步,我们需要学会如何下载程序:WCH的蓝牙芯片CH57x/CH58x大部分是支持串口烧录、USB烧录和LINK烧录的,除了一些特殊的封装,如571K没有USB口,只支持串口免按键烧录,579F没有仿真口,不支持LINK烧录。仿真下载:ARM内核......
  • CF1882 div.2 做题记录
    A题面扫一遍,令\(b_i\rightarrowb_{i-1}+1\),若\(b_i=a_i\),\(b_i\rightarrowb_i+1\)。点击查看代码#include<bits/stdc++.h>#defineullunsignedlonglong#definelllonglong#definepiipair<int,int>#definepdipair<double,int>#definepb......
  • 使用vite插件进行低代码平台自定义开发(手机版自定义范例)
    前言Youtube上的前端网红「Theo」在React文档仓库发起了一个Pullrequest,号召React文档不要再默认推荐CRA(createreactapp),而是应该将Vite作为构建应用的首选。vite的影响力已经从vue蔓延到了react,可见在前端工程化开发中,它已经越来越流行,是时候该从webpack切换到vite了。为什么......
  • 基于Java的高校竞赛管理系统设计与实现(亮点:发起比赛、报名、审核、评委打分、获奖排名
    高校竞赛管理系统一、前言二、我的优势2.1自己的网站2.2自己的小程序(小蔡coding)2.3有保障的售后2.4福利三、开发环境与技术3.1MySQL数据库3.2Vue前端技术3.3SpringBoot框架3.4微信小程序四、功能设计4.1主要功能描述4.2系统角色五、系统主要功能展示5.1前端展示5.1.1......
  • cenos7 内核升级
    1.查看操作系统内核版本$uname-r3.10.0-1062.4.1.el7.x86_642.安装ELRepo官网地址:http://elrepo.org/tiki/tiki-index.php$rpm--importhttps://www.elrepo.org/RPM-GPG-KEY-elrepo.org$yuminstallhttps://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm3.......
  • CH9140,CH9141,CH9143异同点
    原文链接:https://www.cnblogs.com/frontier/p/17361264.html 9140:是一款蓝牙转串口芯片,芯片支持蓝牙主从一体模式或从机模式,支持蓝牙BLE4.2。串口波特率最高1Mbps,支持MODEM联络信号,蓝牙主从模式可以自动连接或绑定。智能配对功能当CH9140芯片处于主从一体模式时,无需......
  • 学习cillium开源项目tetragon
    部署安装安装很方便,注意环境要求,官方说明文档基于的内核版本是ubuntu5.19.0.可参考https://tetragon.cilium.io/docs/getting-started/kubernetes-quickstart-guide/.安装完成后,查看tetragon监听端口如下所示:#netstat-apn|greptetragontcp00127.0.0.1:5432......
  • docker-compose部署rabbitmq关键配置点
    部署关键配置点单一模式即单机情况不做集群,就单独运行一个rabbitmq而已。普通模式默认模式,以两个节点(rabbit01、rabbit02)为例来进行说明。对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列的结构。当消息进入rabbi......