三菱PLC通信(MC协议A-1E和Qna-3E模式)

2 篇文章 1 订阅

1、首先看一下网络模型

UDP协议是无连接,尽最大可能交付报文,没有拥塞控制面向报文(不分割、不合并) 

TCP面向连接,提供可靠交付,有流量控制、拥塞控制面向字节流(从上层传下的数据进行分割,分割成合适运输的数据块)只能是一对一连接

 

2、三菱的PLC通信

在三菱的PLC通信的MC协议中,分为串行通信的报文和以太网接口的报文。
在串口通信中,共有以下几种帧,其中1C,2C,3C帧支持格式1,2,3,4,在C帧里支持格式5通信

  1. 4C帧,QnA系列串行通信模块专用协议(Qna扩展帧)
  2. 3C帧,QnA系列串行通信模块专用协议(Qna帧)
  3. 2C帧,QnA系列串行通信模块专用协议(Qna简易帧)
  4. 1C帧,A系列计算机链接模块专用协议

在以太网通信中,共有以下几种帧,每种帧支持二进制和ASCII格式。A-1E为较早的通信版本,对地址的操作范围有限(数据寄存器区的D0~D6143、D9000~D9255),Qna-3E可访问D0~D12287数据

  1. 4E帧,是3E帧上附加了“序列号”。
  2. 3E帧,QnA系列以太网接口模块的报文格式,兼容SLMP的报文格式
  3. 1E帧,A系列以太网接口模块的报文格式

Demo利用MC协议的A-1E模式,使用ASCII进行通信,基本实现int、float、bit的单点及批量的读写测。试,及利用异步监视PLC某点值的变化,使用PLC 的脉冲模拟数据的变化。代码编写未使用OOP思想,后期需要进行代码的优化

1、MC协议帧,A-1E帧

1、读还是写,字还是位 

 

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using Microsoft.VisualBasic;
using Microsoft.CodeAnalysis.VisualBasic;
using System.Threading;

namespace MCFx
{
    public partial class Form1 : Form
    {


        public Form1()
        {
            InitializeComponent();
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            //A-1E只能操作D0~D6143,D9000~D9255
            groupBox1.Enabled = false;
        }
        private static TcpClient Client;
        private string IpAddress;
        private int PortNum;
        private static byte[] Buffer; //=new byte[256];

        private byte[] InBuff = new byte[1532];
        private static string TxCommand;
        private static string RxResponse;
        private static string Temp;
        private static int j;
        double[] Dreg = new double[65536];
        //private double[] Dreg;
        private string DregStr;
        private string SubHeader;

        private int Muloffset;

        //PLC连接
        private void ConPlc(string IpAddress, int PortNum)
        {
            IpAddress = IpAddress;
            PortNum = PortNum;
            Client = new TcpClient();
            try
            {
                Client.Connect(IpAddress, PortNum);
                if (Client.Connected == true)
                {
                    groupBox1.Enabled = true;
                    txtError.Text = " Success Connection";
                }
                else { MessageBox.Show("Connection Fail"); }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Connection Fail,Next return code will be reback:{0}", ex.Message);
            }
        }

        //PLC断开连接
        private void DisconPlc()
        {
            try
            {
                if (Client == null) { MessageBox.Show("Not Connection PLC "); txtError.Text = "Not Connection PLC "; }
                else
                {
                    Client.GetStream().Close();
                    Client.Close();
                    if (Client.Connected == false)
                    {
                        txtError.Text = "Success DisConnection PLC";
                    }
                    groupBox1.Enabled = false;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Not Connection PLC ");
            }
        }




        private bool DataQuery(string offset, string num)
        {
            if (offset == "")
            {
                MessageBox.Show("Please input your offset");
                return false;
            }
            else if (num == "")
            {
                MessageBox.Show("Please input your ElementNum");
                return false;
            }
            else { return true; }

        }
        //连接PLC
        private void button7_Click(object sender, EventArgs e)
        {
            string IpAddress = txtIP.Text;
            int PortNum = int.Parse(txtPort.Text);
            ConPlc(IpAddress, PortNum);
        }


        //整型批量读  D区
        private void button1_Click(object sender, EventArgs e)
        {
            double[] DregInt = new double[25536];

            //使用A互换1E结构的命令,读出D0~D4(5个点)
            TxCommand = "01 FF 000A 4420 00000000 05 00";   //二进制通信,以字为单位成批读出
            //    读字单位 PC号 ASCii 起始地址    个数
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtoffset.Text, txtFloatNum.Text) == true)
            {
                //读取int个数处理
                int num = int.Parse(txtFloatNum.Text);
                //string HexNum = '0' + (num * 2).ToString();
                string HexNum = string.Format("{0:X}", num);   //大写对大写X x     //122
                HexNum = HexNum.ToString().PadLeft(2, '0');   //不够两个左边补0

                TxCommand = TxCommand.Remove(20, 2);
                TxCommand = TxCommand.Insert(20, HexNum);

                //偏移量处理。比如从D1开始读
                int offset = int.Parse(txtoffset.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);

                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);

                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);
                SubHeader = RxResponse.Substring(2, 2);//开始的第三位取两个
                if (SubHeader == "00")      //正常响应
                {
                    //整型的16位批量处理
                    Temp = "";   //初始化输出字符
                    for (j = 0; j <= num - 1; j++)     //读五个整型的处理
                    {
                        string DregStr = RxResponse.Substring(j * 4 + 4, 4);
                        DregInt[j] = Convert.ToInt32(DregStr, 16);        //十六进制转化为十进制
                                                                          //Temp = Temp + string.Format(DregInt[j].ToString(), "#####0") + " ";   //补全六位,第六位补位0
                        listBox1.Items.Add("D" + offset + ": " + DregInt[j]);
                        offset = offset + 1;
                    }
                    //listBox1.Items.Insert(listBox1.Items.Count, Temp);
                }
                else if (SubHeader == "5B")
                {
                    Temp = "Terminate Code" + SubHeader + "  Error Code" + RxResponse.Substring(5, 2);
                    listBox1.Items.Insert(listBox1.Items.Count, Temp);
                }
                else
                {
                    Temp = "Terminate Code" + SubHeader + "END";
                    listBox1.Items.Insert(listBox1.Items.Count, Temp);
                }
                listBox1.SelectedIndex = listBox1.Items.Count - 1;
            }

        }

        //字单值写入
        private void button2_Click(object sender, EventArgs e)
        {
            TxCommand = "03 FF 000A 4420 0000 0000 01 00 1111";
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtAddrWrite.Text, txtWriteContent.Text) == true)
            {
                //偏移量处理
                int offset = int.Parse(txtAddrWrite.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);

                //写入内容处理
                int content = int.Parse(txtWriteContent.Text);
                string HexContent = string.Format("{0:X}", content);
                HexContent = HexContent.ToString().PadLeft(4, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(24, 4);
                TxCommand = TxCommand.Insert(24, HexContent);



                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);
                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);    //返回8300
                SubHeader = RxResponse.Substring(2, 2);
                if (SubHeader == "00")      //正常响应
                {
                    MessageBox.Show("Success Write!");
                }
            }

        }




        //ASCII 位成批读   M区
        private void button4_Click(object sender, EventArgs e)
        {
            //TxCommand = "00 FF 0A00 64000000 204D 0C 00";  //位读M100~M111
            //ASCII
            TxCommand = "00 FF 000A 4D20 0000 000A 05 00";  //位读M10~M14  读五个补成六个
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtoffset.Text, txtFloatNum.Text) == true)
            {
                //读取int个数处理
                int num = int.Parse(txtFloatNum.Text);
                //string HexNum = '0' + (num * 2).ToString();
                string HexNum = string.Format("{0:X}", num);   //大写对大写X x     //122
                HexNum = HexNum.ToString().PadLeft(2, '0');   //不够两个左边补0

                TxCommand = TxCommand.Remove(20, 2);
                TxCommand = TxCommand.Insert(20, HexNum);

                //偏移量处理。比如从D1开始读
                int offset = int.Parse(txtoffset.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);

                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);
                // 0000 0000 0000 0000 0000
                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);

                SubHeader = RxResponse.Substring(2, 2);

                listBox1.SelectedIndex = listBox1.Items.Count - 1;
            }
        }

        //ASCII 位成批写
        private void button5_Click(object sender, EventArgs e)
        {
            TxCommand = "02 FF 000A 4D20 0000 0000 01 00";
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtMulOffset.Text, null) == true)
            {
                int a = listBox2.Items.Count;
                //偏移量处理
                int offset = int.Parse(txtMulOffset.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);


                //写入个数处理
                int num = a;
                string HexNum = string.Format("{0:X}", num);   //大写对大写X x     //122
                HexNum = HexNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(20, 2);
                TxCommand = TxCommand.Insert(20, HexNum);

                //写入内容处理
                for (int i = 0; i < a; i++)
                {

                    string a1 = listBox2.Items[i].ToString();
                    int black = a1.LastIndexOf(" ") + 1;
                    int leng = a1.Length;
                    a1 = a1.Substring(black, leng - black);
                    int content = int.Parse(a1);
                    string HexContent = string.Format("{0:X}", content);
                    TxCommand = TxCommand + HexContent;
                }
                if (a % 2 != 0)
                {
                    TxCommand = TxCommand + "0"; //偶数写入
                }

                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);
                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);    //返回8300
                SubHeader = RxResponse.Substring(2, 2);
                if (SubHeader == "00")      //正常响应
                {
                    MessageBox.Show("Success Write!");
                    checkBox1.Enabled = true;
                    checkBox2.Enabled = true;
                    checkBox3.Enabled = true;
                }
            }


        }


        //float值 单值读
        private void button6_Click(object sender, EventArgs e)
        {

            //使用A互换1E结构的命令,读出D0~D4(5个点)
            TxCommand = "01 FF 000A 4420 00000000 02 00";   //二进制通信,以字为单位成批读出
            //    读字单位 PC号 ASCii 起始地址    个数
            TxCommand = TxCommand.Replace(" ", "");
            if (DataQuery(txtAddSingleValue.Text, null) == true)
            {
                //偏移量处理。比如从D1开始读
                int offset = int.Parse(txtAddSingleValue.Text);
                string OffsetNum = string.Format("{0:X}", offset * 2);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);

                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);

                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                //CCCD——》0.1
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);
                SubHeader = RxResponse.Substring(2, 2);//开始的第三位取两个
                if (SubHeader == "00")      //正常响应
                {
                    float32位单值处理
                    string dataAll = RxResponse.Substring(4, 8);
                    string str0 = dataAll.Substring(2, 2);
                    string str1 = dataAll.Substring(0, 2);
                    string str2 = dataAll.Substring(6, 2);
                    string str3 = dataAll.Substring(4, 2);
                    //byte[] bytes = BitConverter.GetBytes(floatValue);//浮点数转数组:
                    byte[] bytes = new byte[4];
                    CC CD 3D CC
                    1  0  3  2
                    每两个十六进制组成一个字节 
                    bytes[0] = (byte)Convert.ToInt32(str0, 16);
                    bytes[1] = (byte)Convert.ToInt32(str1, 16);
                    bytes[2] = (byte)Convert.ToInt32(str2, 16);
                    bytes[3] = (byte)Convert.ToInt32(str3, 16);
                    float f33 = BitConverter.ToSingle(bytes, 0);
                    //listBox1.Items.Insert(listBox1.Items.Count, f33);
                    listBox1.Items.Add("D" + offset + ": " + f33);

                }
                else { MessageBox.Show("Data Read Error"); }
            }
        }

        //断开连接PLC
        private void button8_Click(object sender, EventArgs e)
        {
            DisconPlc();
        }

        //字随机写入  ====
        private void button3_Click(object sender, EventArgs e)
        {

        }

        //位随机写入
        private void button9_Click(object sender, EventArgs e)
        {

        }

        private void button10_Click(object sender, EventArgs e)
        {
            TxCommand = "01 FF 000A 4420 00000011 00 00";   //二进制通信,以字为单位成批读出
            //    读字单位 PC号 ASCii 起始地址    个数
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtoffset.Text, txtFloatNum.Text) == true)
            {
                //读取float个数处理
                int num = int.Parse(txtFloatNum.Text);
                //string HexNum = '0' + (num * 2).ToString();
                string HexNum = string.Format("{0:X}", num * 2);   //大写对大写X x     //122
                HexNum = HexNum.ToString().PadLeft(2, '0');   //不够两个左边补0

                TxCommand = TxCommand.Remove(20, 2);
                TxCommand = TxCommand.Insert(20, HexNum);

                //偏移量处理。比如从D1开始读
                int offset = int.Parse(txtoffset.Text);
                string OffsetNum = string.Format("{0:X}", offset * 2);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);

                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);

                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);
                SubHeader = RxResponse.Substring(2, 2);//开始的第三位取两个
                if (SubHeader == "00")      //正常响应
                {
                    //float处理
                    float Temp = 0;   //初始化输出字符   默认小数点后两位
                                      //double Temp = 0;        //取小数点后的全部
                    for (j = 0; j <= num - 1; j++)     //读五个整型的处理
                    {
                        string DregStr = RxResponse.Substring(j * 8 + 4, 8);
                        //      Dreg[j] = Convert.ToInt32(DregStr, 16);        //十六进制转化为十进制
                        float32位单值处理
                        string str0 = DregStr.Substring(2, 2);
                        string str1 = DregStr.Substring(0, 2);
                        string str2 = DregStr.Substring(6, 2);
                        string str3 = DregStr.Substring(4, 2);
                        //byte[] bytes = BitConverter.GetBytes(floatValue);//浮点数转数组:
                        byte[] bytes = new byte[4];
                        CC CD 3D CC
                        1  0  3  2
                        每两个十六进制组成一个字节 
                        bytes[0] = (byte)Convert.ToInt32(str0, 16);
                        bytes[1] = (byte)Convert.ToInt32(str1, 16);
                        bytes[2] = (byte)Convert.ToInt32(str2, 16);
                        bytes[3] = (byte)Convert.ToInt32(str3, 16);
                        Temp = BitConverter.ToSingle(bytes, 0);
                        listBox1.Items.Add("D" + offset + ": " + Temp);
                        offset = offset + 2;
                    }
                }

            }
            else if (SubHeader == "5B")
            {
                Temp = "Terminate Code" + SubHeader + "  Error Code" + RxResponse.Substring(5, 2);
                listBox1.Items.Insert(listBox1.Items.Count, Temp);
            }
            else
            {
                Temp = "Terminate Code" + SubHeader + "END";
                listBox1.Items.Insert(listBox1.Items.Count, Temp);
            }
            listBox1.SelectedIndex = listBox1.Items.Count - 1;
        }



        #region 异步传值
        //第一个值
        private static string param = "";
        private void OnRead(string sParam)
        {
            param = sParam;
            Object[] list = { this, System.EventArgs.Empty };
            this.lblShow.BeginInvoke(new EventHandler(LabelShow), list);
        }
        protected void LabelShow(Object o, EventArgs e)   //显示方法
        {
            this.lblShow.Text = param;
        }

        public delegate void ReadParamEventHandler(string sParam);     //定义委托


        //第二个值
        private static string param2 = "";
        private void OnRead2(string sParam)
        {
            param2 = sParam;
            Object[] list = { this, System.EventArgs.Empty };
            this.lblShow.BeginInvoke(new EventHandler(LabelShow2), list);
        }
        protected void LabelShow2(Object o, EventArgs e)   //显示方法
        {
            this.lblShow2.Text = param2;
        }
        public delegate void ReadParamEventHandler2(string sParam);     //定义委托



        class MyThread
        {
            public Thread thread1;
            private static ReadParamEventHandler OnReadParamEvent;   //定义委托的一个实例
            public MyThread()     //定义线程
            {
                thread1 = new Thread(new ThreadStart(MyRead));
                thread1.IsBackground = true;
                thread1.Start();
            }
            public event ReadParamEventHandler ReadParam     //定义事件
            {
                add { OnReadParamEvent += new ReadParamEventHandler(value); }
                remove { OnReadParamEvent -= new ReadParamEventHandler(value); }
            }

            public void MyRead()
            {
                double[] DregInt = new double[25536];
                byte[] InBuff = new byte[1532];
                int i = 0;
                while (true)
                {
                    Thread.Sleep(100);
                    TxCommand = "01 FF 000A 4420 00000035 01 00";   //二进制通信,以字为单位成批读出
                    TxCommand = TxCommand.Replace(" ", "");
                    Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                    //发送命令
                    Client.GetStream().Write(Buffer, 0, Buffer.Length);

                    //等待以太网适配器的响应
                    while (!Client.GetStream().DataAvailable)
                    {
                        Application.DoEvents();
                    }
                    Client.GetStream().Read(InBuff, 0, InBuff.Length);
                    RxResponse = System.Text.Encoding.Default.GetString(InBuff);
                    //整型的16位批量处理
                    Temp = "";   //初始化输出字符

                    string DregStr = RxResponse.Substring(0 * 4 + 4, 4);
                    //十六进制转化为十进                                                 //Temp = Temp + string.Format(DregInt[j].ToString(), "#####0") + " ";   //补全六位,第六位补位0
                    i = Convert.ToInt32(DregStr, 16);
                    OnReadParamEvent(i.ToString());    //触发事件
                }
            }
        }
        class MyThread2
        {
            public Thread thread2;
            private static ReadParamEventHandler2 OnReadParamEvent2;   //定义委托的一个实例
            public MyThread2()     //定义线程
            {
                thread2 = new Thread(new ThreadStart(MyRead2));
                thread2.IsBackground = true;
                thread2.Start();
            }
            public event ReadParamEventHandler ReadParam2     //定义事件
            {
                add { OnReadParamEvent2 += new ReadParamEventHandler2(value); }
                remove { OnReadParamEvent2 -= new ReadParamEventHandler2(value); }
            }

            public void MyRead2()
            {
                double[] DregInt = new double[25536];
                byte[] InBuff = new byte[1532];
                int i = 0;
                while (true)
                {
                    Thread.Sleep(100);
                    TxCommand = "01 FF 000A 4420 00000036 01 00";   //二进制通信,以字为单位成批读出
                    TxCommand = TxCommand.Replace(" ", "");
                    Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                    //发送命令
                    Client.GetStream().Write(Buffer, 0, Buffer.Length);
                    //等待以太网适配器的响应
                    while (!Client.GetStream().DataAvailable)
                    {
                        Application.DoEvents();
                    }
                    Client.GetStream().Read(InBuff, 0, InBuff.Length);
                    RxResponse = System.Text.Encoding.Default.GetString(InBuff);

                    //整型的16位批量处理
                    Temp = "";   //初始化输出字符

                    string DregStr = RxResponse.Substring(0 * 4 + 4, 4);
                    //十六进制转化为十进                                                 //Temp = Temp + string.Format(DregInt[j].ToString(), "#####0") + " ";   //补全六位,第六位补位0

                    i = Convert.ToInt32(DregStr, 16);
                    OnReadParamEvent2(i.ToString());    //触发事件
                }
            }
        }

        private void button11_Click_1(object sender, EventArgs e)
        {
            MyThread thread1 = new MyThread();
            thread1.ReadParam += this.OnRead;    //订阅线程类中的事件

            MyThread2 thread2 = new MyThread2();
            thread2.ReadParam2 += this.OnRead2;
        }
        #endregion



        #region  委托事件取值
        public delegate void SendValue(string a);
        public event SendValue send_event;
        #endregion

        private void button12_Click(object sender, EventArgs e)
        {
            ShowData();
        }
        private void ShowData()
        {
            double[] DregInt = new double[25536];
            this.Invoke(new MethodInvoker(delegate
            {
                while (true)
                {
                    Thread.Sleep(100);
                    TxCommand = "01 FF 000A 4420 00000035 02 00";   //二进制通信,以字为单位成批读出
                    TxCommand = TxCommand.Replace(" ", "");
                    Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                    //发送命令
                    Client.GetStream().Write(Buffer, 0, Buffer.Length);
                    //等待以太网适配器的响应
                    while (!Client.GetStream().DataAvailable)
                    {
                        Application.DoEvents();
                    }
                    Client.GetStream().Read(InBuff, 0, InBuff.Length);
                    RxResponse = System.Text.Encoding.Default.GetString(InBuff);

                    //整型的16位批量处理
                    Temp = "";   //初始化输出字符
                    for (j = 0; j <= 1; j++)     //读五个整型的处理
                    {
                        string i = RxResponse.Substring(j * 4 + 4, 4);
                        DregInt[j] = Convert.ToInt32(i, 16);        //十六进制转化为十进制
                    }


                    label12.Text = Convert.ToInt32(DregInt[0]).ToString();
                    label13.Text = Convert.ToInt32(DregInt[1]).ToString();
                }
            }));
        }

        //字单值读
        private void button13_Click(object sender, EventArgs e)
        {
            double[] DregInt = new double[25536];

            //使用A互换1E结构的命令,读出D0~D4(5个点)
            TxCommand = "01 FF 000A 4420 00000000 01 00";   //二进制通信,以字为单位成批读出
            //    读字单位 PC号 ASCii 起始地址    个数
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtAddSingleValue.Text, null) == true)
            {
                //偏移量处理。比如从D1开始读
                int offset = int.Parse(txtAddSingleValue.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);

                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);

                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);
                SubHeader = RxResponse.Substring(2, 2);//开始的第三位取两个
                if (SubHeader == "00")      //正常响应
                {

                    string DregStr = RxResponse.Substring(4, 4);
                    DregInt[j] = Convert.ToInt32(DregStr, 16);        //十六进制转化为十进制
                                                                      //Temp = Temp + string.Format(DregInt[j].ToString(), "#####0") + " ";   //补全六位,第六位补位0
                    listBox1.Items.Add("D" + offset + ": " + DregInt[j]);
                }
                else if (SubHeader == "5B")
                {
                    Temp = "Terminate Code" + SubHeader + "  Error Code" + RxResponse.Substring(5, 2);
                    listBox1.Items.Insert(listBox1.Items.Count, Temp);
                }
                else
                {
                    Temp = "Terminate Code" + SubHeader + "END";
                    listBox1.Items.Insert(listBox1.Items.Count, Temp);
                }
                listBox1.SelectedIndex = listBox1.Items.Count - 1;
            }
        }

        //位的单值读
        private void button14_Click(object sender, EventArgs e)
        {
            TxCommand = "00 FF 000A 4D20 0000 0000 01 00";  //位读M10~M14  读五个补成六个
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtAddSingleValue.Text, null) == true)
            {
                //偏移量处理。
                int offset = int.Parse(txtAddSingleValue.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);

                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);
                // 0000 0000 0000 0000 0000
                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);

                SubHeader = RxResponse.Substring(2, 2);
                if (SubHeader == "00")      //正常响应
                {
                    //位的批量处理
                    string DregStr = RxResponse.Substring(4, 1);
                    Dreg[j] = Convert.ToInt32(DregStr, 16);        //十六进制转化为十进制
                    listBox1.Items.Add("M" + offset + ": " + Dreg[j]);
                }
                else { MessageBox.Show("位数据读取错误"); }
            }
        }

        private void ShowLabel(object sender, EventArgs e)
        {
            if (txtMulOffset.Text != "")
            {
                Muloffset = int.Parse(txtMulOffset.Text);
                //label20.Text = "D" + txtMulOffset.Text;
                //label21.Text = "D" + (int.Parse(txtMulOffset.Text) + 1);
                //label22.Text = "D" + (int.Parse(txtMulOffset.Text) + 2);
            }
            else
            {
                //label20.Text = txtMulOffset.Text;
                //label21.Text = txtMulOffset.Text;
                //label22.Text = txtMulOffset.Text;
            }
        }

        //位单值写入
        private void button16_Click(object sender, EventArgs e)
        {

            // TxCommand = "02 FF 000A 4D20 0000 000A 08 00  11 11 10 11";  //16点 位写位M10 写8位  只能  左高右低 搞两位 1101 0011  LHLH
            TxCommand = "02 FF 000A 4D20 0000 0000 01 00  0";
            TxCommand = TxCommand.Replace(" ", "");
            if (DataQuery(txtAddrWrite.Text, txtWriteContent.Text) == true)
            {
                //偏移量处理
                int offset = int.Parse(txtAddrWrite.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);

                //写入内容处理
                int content = int.Parse(txtWriteContent.Text);
                string HexContent = string.Format("{0:X}", content);
                TxCommand = TxCommand.Remove(24, 1);
                TxCommand = TxCommand.Insert(24, HexContent);

                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);
                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);   //8200
                SubHeader = RxResponse.Substring(2, 2);
                if (SubHeader == "00")
                {
                    MessageBox.Show("Success Write");
                }
            }
        }

        //float单值写
        private void button17_Click(object sender, EventArgs e)
        {

            byte[] HexValue = new byte[4];   //4个字节32位,1个字节8位FF
            string[] DregInt = new string[4];


            TxCommand = "03 FF 000A 4420 0000 0000 02 00";
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtAddrWrite.Text, txtWriteContent.Text) == true)
            {

                //写入内容处理
                float content1 = float.Parse(txtWriteContent.Text);
                var Hex_Value = FloatToHex(content1);      //转化为二进制
                HexValue = HexToFloat(Hex_Value);  //转化为16进制的数组

                for (j = 0; j <= 3; j++)     //处理一个float
                {
                    int num = HexValue[j];
                    string HexNum = string.Format("{0:X}", num);   //大写对大写X x    
                    HexNum = HexNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                    DregInt[j] = HexNum;   //大写对大写X x    
                }
                string content = "";

                //前四个和后四个换位置
                for (int i = DregInt.Length / 2 - 1; i >= 0; i--)
                {
                    content += DregInt[i];
                }
                for (int i = DregInt.Length / 2 + 1; i > 1; i--)
                {
                    // MessageBox.Show(i.ToString());
                    content += DregInt[i];
                }


                TxCommand = TxCommand.Insert(24, content);

                // 03FF 000A 4420 0000 0000 02 00 00 0000 01
                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);
                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);    //返回8300
                SubHeader = RxResponse.Substring(2, 2);
                if (SubHeader == "00")      //正常响应
                {
                    MessageBox.Show("Success Write!");
                }
            }

        }

        private void button15_Click(object sender, EventArgs e)
        {
            TxCommand = "03 FF 000A 4420 0000 0000 01 00";
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtMulOffset.Text, null) == true)
            {
                int a = listBox2.Items.Count;
                //偏移量处理
                int offset = int.Parse(txtMulOffset.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);


                //写入个数处理
                int num = a;
                string HexNum = string.Format("{0:X}", num);   //大写对大写X x     //122
                HexNum = HexNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(20, 2);
                TxCommand = TxCommand.Insert(20, HexNum);

                //写入内容处理
                //string[] content = new string[int.Parse(txtMulNum.Text)];

                string[] content = new string[a];
                for (int i = 0; i < a; i++)
                {

                    string a1 = listBox2.Items[i].ToString();
                    int black = a1.LastIndexOf(" ") + 1;
                    int leng = a1.Length;
                    a1 = a1.Substring(black, leng - black);

                    string HexContent = string.Format("{0:X}", int.Parse(a1));
                    HexContent = HexContent.ToString().PadLeft(4, '0');   //不够两个左边补0
                    TxCommand = TxCommand.Insert(24 + i * 4, HexContent);
                }

                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);
                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);    //返回8300
                SubHeader = RxResponse.Substring(2, 2);
                if (SubHeader == "00")      //正常响应
                {
                    MessageBox.Show("Success Write!");
                    checkBox1.Enabled = true;
                    checkBox2.Enabled = true;
                    checkBox3.Enabled = true;
                }
            }
        }

        private static string FloatToHex(float value)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            StringBuilder stringBuffer = new StringBuilder();
            for (int i = 0; i < bytes.Length; i++)
            {
                if (i != 0)
                {
                    stringBuffer.Insert(0, " ");
                }
                string hex = Convert.ToString(bytes[i], 2);
                stringBuffer.Insert(0, hex);
                //位数不够补0
                for (int j = hex.Length; j < 8; j++)
                {
                    stringBuffer.Insert(0, "0");
                }
            }
            return stringBuffer.ToString();
        }
        private static byte[] HexToFloat(string str)
        {
            str = str.Replace(" ", string.Empty);
            if (str.Length != 32)
            {
                MessageBox.Show("数据长度错误");
                // return float.NaN;
            }
            byte[] intBuffer = new byte[4];
            //将二进制串按字节逆序化(一个字节八位)
            for (int i = 0; i < 4; i++)
            {
                string hex = str.Substring(24 - 8 * i, 8);
                intBuffer[i] = Convert.ToByte(hex, 2);
            }
            //return BitConverter.ToString(intBuffer, 0);
            return intBuffer;
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void button19_Click(object sender, EventArgs e)
        {
            //int
            if (checkBox1.Checked && !checkBox2.Checked && !checkBox3.Checked)
            {
                listBox2.Items.Add("D" + Muloffset + ": " + MulContent.Text);
                Muloffset += 1;
                checkBox1.Enabled = false;
                checkBox2.Enabled = false;
                checkBox3.Enabled = false;
            }
            //float
            else if (!checkBox1.Checked && checkBox2.Checked && !checkBox3.Checked)
            {
                listBox2.Items.Add("D" + Muloffset + ": " + MulContent.Text);
                Muloffset += 2;
                checkBox1.Enabled = false;
                checkBox2.Enabled = false;
                checkBox3.Enabled = false;
            }
            //M 位
            else if (!checkBox1.Checked && !checkBox2.Checked && checkBox3.Checked)
            {
                listBox2.Items.Add("M" + Muloffset + ": " + MulContent.Text);
                Muloffset += 1;
                checkBox1.Enabled = false;
                checkBox2.Enabled = false;
                checkBox3.Enabled = false;
            }
            else { MessageBox.Show("Please check add data type"); }

        }

        private void button20_Click(object sender, EventArgs e)
        {
            listBox2.Items.Clear();
            Muloffset = int.Parse(txtMulOffset.Text);
        }

        private void button18_Click(object sender, EventArgs e)
        {
            byte[] HexValue = new byte[4];   //4个字节32位,1个字节8位FF
            string[] DregInt = new string[4];
            int a = listBox2.Items.Count;

            TxCommand = "03 FF 000A 4420 0000 0000 02 00";
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtMulOffset.Text, null) == true)
            {

                //偏移量处理
                int offset = int.Parse(txtMulOffset.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122
                OffsetNum = OffsetNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(18, 2);
                TxCommand = TxCommand.Insert(18, OffsetNum);


                //写入个数处理
                int num = a;
                string HexNum = string.Format("{0:X}", num * 2);   //大写对大写X x     //122
                HexNum = HexNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                TxCommand = TxCommand.Remove(20, 2);
                TxCommand = TxCommand.Insert(20, HexNum);

                //写入内容处理
                for (int k = 0; k < a; k++)
                {
                    MessageBox.Show(k.ToString());
                    string a1 = listBox2.Items[k].ToString();
                    int black = a1.LastIndexOf(" ") + 1;
                    int leng = a1.Length;
                    a1 = a1.Substring(black, leng - black);

                    float b2 = float.Parse(a1);


                    var Hex_Value = FloatToHex(b2);      //转化为二进制
                    HexValue = HexToFloat(Hex_Value);  //转化为16进制的数组

                    for (j = 0; j <= 3; j++)     //处理一个float
                    {
                        int num1 = HexValue[j];
                        string HexNum1 = string.Format("{0:X}", num1);   //大写对大写X x    
                        HexNum1 = HexNum1.ToString().PadLeft(2, '0');   //不够两个左边补0
                        DregInt[j] = HexNum1;   //大写对大写X x    
                    }
                    string contentAdd = "";

                    //前四个和后四个换位置
                    for (int i = DregInt.Length / 2 - 1; i >= 0; i--)
                    {
                        contentAdd += DregInt[i];
                    }
                    for (int i = DregInt.Length / 2 + 1; i > 1; i--)
                    {
                        // MessageBox.Show(i.ToString());
                        contentAdd += DregInt[i];
                    }

                    TxCommand = TxCommand + contentAdd;
                }


                // 03FF 000A 4420 0000 0000 02 00 00 0000 01
                Buffer = System.Text.Encoding.Default.GetBytes(TxCommand.Trim().ToCharArray());
                //发送命令
                Client.GetStream().Write(Buffer, 0, Buffer.Length);
                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = System.Text.Encoding.Default.GetString(InBuff);    //返回8300
                SubHeader = RxResponse.Substring(2, 2);
                if (SubHeader == "00")      //正常响应
                {
                    MessageBox.Show("Success Write!");
                    checkBox1.Enabled = true;
                    checkBox2.Enabled = true;
                    checkBox3.Enabled = true;
                }
            }

        }

        //3E二进制通信     转成十六进制 的就能和上面1E的使用了

    }
}

 

 2、MC协议帧,Qna-3E帧

QnA 兼容3E 帧、4E 帧的报文格式

 

 1二进制.读D100开始的连续的20个数据块,也就是读D100~D119的数据;
电脑读命令:  50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00     64 00 00   A8 14 00 (23:19:46:937)

                                                        12字节                               起始地址100            20个
PLC反馈:  D0 00 00 FF FF 03 00 2A 00 00 00 86 F1 00 00 C9 01 00 00 D6 02 00 00 68 02 00 00 2E 02 00 00 00 00 00 00 C3 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (23:19:46:937)
下面解析一下:
电脑读命令: 50 00(命令,副头部)  :,表示发起指令,固定50 00;
         00(网络编号) :上位访问下位,固定00;
         FF(PLC编号) : 上位访问下位,固定FF;
         FF 03(请求目标模块IO编号) : 为大端表示法,值要从小到大看,也就是反过来看,三菱所有的协值都是这样,所以这里是03FF,十进制是1023; 也是固定的;
         00(请求目标模块站编号) : 上位访问下位,固定00;
         0C 00 (请求数据长度): 也要反过来,值是000C,也就是12;表示后面的报文内容的长度是12
         10 00 (CPU监视定时器)  : 表示等待PLC响应的timeout时间;这里 值是0010,十进制是16 ;相当与最大等待时间250ms*16=4秒;实际上PLC一般2,3个毫秒内就响应了;
         01 04 (批量读命令)  :   值是0401(所有值都要反过来看,再说就啰嗦了,后面不说了);表示批量读取;如果是1401就是随机写取;
         00 00 (子命令) : 值是0表示按字读取(1个字=16位),如果值是1就按位读取;
         64 00 00(首地址):地址因为跨度比较大,所以用了3个字节;这里的值是000064,十进制就是100
         A8 (软元件  读取的区域)         : 表示读取PLC寄存器的类型:  这里的A8表示D点;其他常见的有: 90-M点;9C-X点;9D-Y点;B0-ZR外部存储卡
         14 00(读取长度)  :值是0014,十进制就是20;


PLC反馈: D0 00 (响应) :表示反馈信息,固定D0 00;
               00  (网络编号 ): 与上同
               FF  (PLC编号) : 与上同
               FF 03 (请求目标模块IO编号) : 与上同
              00 (请求目标模块站编号): 与上同
              2A 00 (应答数据物理长度):值是002A; 十进制是 42;也就是说后面的:结束代码(2个字节)+值=42;所以值是40个字节;2个字节=1个字;所以值是20个字;
              00 00(结束代码) :可以理解成异常代码,如果正常的话,就是0000
               86 F1 00 00 C9 01 00 00 D6 02 00 00 68 02 00 00 2E 02 00 00 00 00 00 00 C3 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 (反馈的值);这里正好40个字节;
               再啰嗦一下,值要反过来看,所以地址D100=F186;D101=0000,D102=01C9......

求数据长度计算为之后的所有数据,二进制方式两个数字为一个字,ASCII为一个数字一个字,二进制发送时数据的高低位需要调换,ASCII发送带字母起始地址式会返回错误(待解决)。

数据回复

异常回复:0b 00 5b c0 00 ff ff 03 00 01 14 00 00

成功回复:d0 00 00 ff ff 03 00 02 00 00 00

 2.二进制写D100这一个点的值为13,D101这个点的值为14,D102这个点的值为15;
        电脑写命令: 50 00 00 FF FF 03 00 12 00 10 00 01 14 00 00 64 00 00 A8 03 00 0C 00 0D 00 0E 00 (00:14:55:188)
        PLC反馈: D0 00 00 FF FF 03 00 02 00 00 00 (00:14:55:188)
下面解析一下:
     电脑写命令:
                50 00 (命令)  :意义和读一样
                00(网络编号 ) :意义和读一样
                FF(PLC编号)    :意义和读一样
                FF 03 (请求目标模块IO编号) :意义和读一样
                00(请求目标模块站编号) :意义和读一样
               12 00(请求数据物理长度) :
                           值是0012,也就是十进制18;表示后面的报文内容的长度是20;
                        也就是后面的:cpu监视定时器+命令+子命令+首地址+软元件+长度+值=18;前面有12个字节;所以值是6个字节;也就是3个字;
               10 00(cpu监视定时器):同上
               01 14(命令):跟读的差别是:读是0104,写是0114 ;就是04和14的差别;
              0000(子命令):值是0表示按字读写入1个字=16位),如果值是1就按位写入;
              640000(首地址) :意义和读一样,10进制100;表示从D100这个首地址写入;
              A8(软元件)  :意义和读一样  
              0300(长度): 值是0003 表示连续写入3个长度;
              0C00 0D00  0E00(写入的值): D100=13 ,D101=14,D102=15;
    PLC反馈(所有正常的写入,反馈的信息都固定为这个):
          D0 00(响应) :表示反馈信息,与读取反馈一样,固定D0 00;
          00(网络编号 ):同上
          FF(PLC编号)  :同上
          FF 03 (请求目标模块IO编号) :同上
          00(请求目标模块站编号) :同上
          02 00(应答数据物理长度): 就是后面的 00 00 正好两个字节,所以这里值=2;
          00 00(结束代码)  :可以理解成异常代码,如果正常的话,就是0000

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MCFx
{
    public partial class MC_3E : Form
    {
        private static TcpClient Client;
        private string IpAddress;    //IP地址
        private int PortNum;         //端口号

        private static string TxCommand;    //发送的命令串
        private static string RxResponse;   //响应返回的字符串
        private static string Temp;

        private byte[] InBuff = new byte[64];
        private double[] Dreg;
        private string DregStr;
        private string SubHeader;   //判断响应是否成功的头信息
        private string ResponseData;   //判断响应是否成功的头信息
        public MC_3E()
        {
            InitializeComponent();
        }
        private void MC_3E_Load(object sender, EventArgs e)
        {
            groupBox3.Enabled = false;
        }

        #region PLC的连接和断开
        //PLC连接按钮
        private void button7_Click(object sender, EventArgs e)
        {
            string IpAddress = txtIP.Text;
            int PortNum = int.Parse(txtPort.Text);
            ConPlc(IpAddress, PortNum);
        }

        //PLC连接方法
        private void ConPlc(string ipAddress, int portNum)
        {
            IpAddress = ipAddress;
            PortNum = portNum;
            Client = new TcpClient();
            try
            {
                Client.Connect(IpAddress, PortNum);
                if (Client.Connected == true)
                {
                    btnCon.Enabled = false;
                    groupBox3.Enabled = true;
                    txtError.Text = " Success Connection";
                }
                else { MessageBox.Show("Connection Fail"); }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Connection Fail,Next return code will be reback:{0}", ex.Message);
            }
        }

        //断开PLC连接
        private void button8_Click(object sender, EventArgs e)
        {
            DisconPlc();
        }
        //PLC断开连接方法
        private void DisconPlc()
        {
            try
            {
                if (Client == null) { MessageBox.Show("Not Connection PLC "); txtError.Text = "Not Connection PLC "; }
                else
                {
                    Client.GetStream().Close();
                    Client.Close();
                    if (Client.Connected == false)
                    {
                        txtError.Text = "Success DisConnection PLC";
                    }
                    groupBox1.Enabled = false;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Not Connection PLC ");
            }
        }
        #endregion

        private bool DataQuery(string offset, string num)
        {
            if (offset == "")
            {
                MessageBox.Show("Please input your offset");
                return false;
            }
            else if (num == "")
            {
                MessageBox.Show("Please input your ElementNum");
                return false;
            }
            else { return true; }

        }


        #region PLC读取 int float和bit数据
        // int 读
        private void button22_Click(object sender, EventArgs e)
        {
            double[] DregInt = new double[1024];   //定义缓存数组

            //使用二进制 3E结构的命令,读出D100~D102(3个点)
            //TxCommand = "50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 58 1B 00 A8 03 00";  //有头无数据
            TxCommand = "500000FFFF0300 0C00 1000 0104 00 00 640000 A8 03 00";//二进制D100-103  A8代表的是D区  M区是90
            /*发送命令分析
             * 500000FFFF0300  头部固定信息
             * 0C00 :即为000C  表示这个字符串后面的数据长度,就是在0C00后面的字节个数:cpu监视定时器+命令+子命令+首地址+软元件+长度+值=12;
             * 1000 :0010,PLC响应的timeout时间
             * 0104 :0401;批量读  1401为写
             * 0000 :按字读,如果是1就是按位读
             * 640000:000064,首地址,十进制就是100
             * A8 :软元件,读取的区域 A8表示D区  90-M 9C-X 9D-Y 
             * 0300:0003,读取数据长度为3个字
             */

            TxCommand = TxCommand.Replace(" ", "");  //删除空格

            //十六进制转十进制,发送的命令转化成十进制字节进行发送
            byte[] bytes = new byte[TxCommand.Length / 2];
            for (int i = 0; i < TxCommand.Length; i += 2)
                bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);

            Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令
            //等待以太网适配器的响应
            while (!Client.GetStream().DataAvailable)
            {
                Application.DoEvents();
            }
            Client.GetStream().Read(InBuff, 0, InBuff.Length);         //获取响应命令放入InBuff中

            // 1  转化成数组处理
            //InBuff的十进制字节数组转成 十六进制字符串数组了
            //RxResponse = byteToHexStr(InBuff);         //响应的命令转成一串十六进制字符串
            //string[] hexbytes = new string[InBuff.Length];
            //hexbytes = byteToHexStr1(InBuff);
            *字符串数组处理*/
            //string[] hexbytes11 = new string[InBuff.Length - 11 / 2];
            //for (int i = 11; i < hexbytes.Length / 2; i += 2)
            //{
            //    hexbytes11[(i - 11) / 2] = hexbytes[i + 1] + hexbytes[i];
            //}
            //SubHeader = RxResponse.Substring(0, 4);
            //if (SubHeader == "D000")      //正常响应
            //{
            //    for (int i = 0; i < hexbytes11.Length; i++)
            //    {
            //        DregInt[i] = Convert.ToInt32(hexbytes11[i], 16);
            //        listBox1.Items.Add("D : " + DregInt[i]);
            //    }
            //}


            // 2 直接处理响应字符串
            RxResponse = byteToHexStr(InBuff);         //响应的命令转成一串十六进制字符串

            //D000 00FFFF0300 0800 0000 6400 6500 0E00
            /*响应命令分析
             * D000:响应,表示反馈信息,固定D000
             * 0800:值为0008,十进制为8,也就是说在0800后面的:结束代码(2个字节)+ 值=8       //响应的字符串个数处理
             * 0000:结束代码,可以理解成判断响应是否异常的代码,如果正常响应的话就是0000
             */

            //直接字符串处理
            SubHeader = RxResponse.Substring(18, 4);  //截取结束代码
            if (SubHeader == "0000")      //正常响应
            {
                ResponseData = RxResponse.Substring(22, 12);
                int count = ResponseData.Length;
                for (int j = 0; j <= count / 4 - 1; j++)     //读五个整型的处理
                {
                    string DregStr = ResponseData.Substring(j * 4, 4);
                    DregStr = DregStr.Substring(2, 2) + DregStr.Substring(0, 2);  //高低位互换
                    DregInt[j] = Convert.ToInt32(DregStr, 16);        //十六进制转化为十进制  
                    listBox1.Items.Add(DregInt[j]);
                }
            }
            else
            {
                Temp = "Terminate Code" + SubHeader + "  Error Code";
                listBox1.Items.Insert(listBox1.Items.Count, Temp);
            }
        }

        // Float 读
        private void button21_Click(object sender, EventArgs e)
        {
            //使用二进制 3E结构的命令,读出D104 D106(2个float值)
            TxCommand = "500000FF FF 03 00 0C00 1000 0104 0000 680000 A8 04 00";//读四个字节

            TxCommand = TxCommand.Replace(" ", "");

            //十六进制转十进制,发送的命令转化成十进制字节数组
            byte[] bytes = new byte[TxCommand.Length / 2];
            for (int i = 0; i < TxCommand.Length; i += 2)
                bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);

            Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令
            //等待以太网适配器的响应
            while (!Client.GetStream().DataAvailable)
            {
                Application.DoEvents();
            }
            Client.GetStream().Read(InBuff, 0, InBuff.Length);         //获取返回在命令放入InBuff中

            十六进制数组处理
            //string[] hexbytes = new string[InBuff.Length];
            //RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
            //hexbytes = byteToHexStr1(InBuff);            //转成字符串数组了
            //                                             //字符串数组处理
            //string[] hexbytes11 = new string[InBuff.Length - 11 / 2];
            //for (int i = 11; i < hexbytes.Length / 2; i += 2)
            //{
            //    hexbytes11[(i - 11) / 2] = hexbytes[i + 1] + hexbytes[i];
            //}
            //SubHeader = RxResponse.Substring(0, 4);
            //if (SubHeader == "D000")      //正常响应
            //{
            //    byte[] bytes2 = new byte[4];
            //    每两个十六进制组成一个字节 ABCD
            //    bytes2[0] = (byte)Convert.ToInt32(hexbytes[11], 16);
            //    bytes2[1] = (byte)Convert.ToInt32(hexbytes[12], 16);
            //    bytes2[2] = (byte)Convert.ToInt32(hexbytes[13], 16);
            //    bytes2[3] = (byte)Convert.ToInt32(hexbytes[14], 16);
            //    float f33 = BitConverter.ToSingle(bytes2, 0);
            //    listBox1.Items.Add("D float" + ": " + f33);
            //}


            RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
            //D000 00 FFFF 0300 0A000000 CDCC CC3D CCCD 3DCC

            SubHeader = RxResponse.Substring(18, 4);
            if (SubHeader == "0000")      //正常响应
            {
                ResponseData = RxResponse.Substring(22, 12);
                int count = ResponseData.Length;
                //byte[] bytef = new byte[count / 2 - 1];
                //for (int i = 0; i < count / 2 - 1; i++) 
                //{
                //    bytef[i] = (byte)Convert.ToInt32(ResponseData.Substring(i * 4, 2),16);
                //}
                byte[] bytef = new byte[4];
                for (int i = 0; i < 4; i++)
                {
                    string str = ResponseData.Substring(i * 2, 2);
                    bytef[i] = (byte)Convert.ToInt32(str, 16);
                }
                float fValue = BitConverter.ToSingle(bytef, 0);
                listBox1.Items.Add("D float" + ": " + fValue);
            }

        }

        // bit 读
        private void button3_Click(object sender, EventArgs e)
        {

            TxCommand = "50 00 00 FF FF03 00 0C00 10 00 0104 0100 000000 90 08 00";   // 90-M  从M1开始读取八位

            TxCommand = TxCommand.Replace(" ", "");
            //十六进制转十进制 发送的命令转化成十进制
            byte[] bytes = new byte[TxCommand.Length / 2];
            for (int i = 0; i < TxCommand.Length; i += 2)
                bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);
            Client.GetStream().Write(bytes, 0, bytes.Length);
            while (!Client.GetStream().DataAvailable)
            {
                Application.DoEvents();
            }

            Client.GetStream().Read(InBuff, 0, InBuff.Length);         //获取返回在命令放入InBuff中
                                                                       //转成字符串数组了
                                                                       //string[] hexbytes = new string[InBuff.Length];
                                                                       //hexbytes = byteToHexStr1(InBuff);       
            RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
                                                       // D000 00 FF FF03 0006 00 0000 1110 0000
                                                       // D000 00 FF FF03 0006 00 0000 1111 0000 
                                                       // D000 00 FF FF03 0006 00 0000 1111 1000 
                                                       // D000 00 FF FF03 0006 00 0000 1111 1010
                                                       //1234 5678
                                                       // D000 00 FF FF03 0006 000000 1111 1011

            SubHeader = RxResponse.Substring(18, 4);
            if (SubHeader == "0000")      //正常响应
            {
                ResponseData = RxResponse.Substring(22, 8);
                int count = ResponseData.Length;
                string a;
                for (int i = 0; i < 8; i++)
                {
                    a = ResponseData.Substring(i, 1);
                    listBox1.Items.Add("M : " + a);
                }
            }
        }

        #endregion



        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string byteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    returnStr += bytes[i].ToString("X2");
                }
            }
            return returnStr;
        }


        /// <summary>
        /// 字节十进制数组转字节16进制数组
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public static string[] byteToHexStr1(byte[] bytes)
        {
            string returnStr = "";
            string[] returnBytes = new string[bytes.Length];
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    string a = bytes[i].ToString("X2");
                    returnBytes[i] = a;
                    //string转byte[]:
                    //byte[] byteArray = System.Text.Encoding.Default.GetBytes(str);

                    byte[]转string:
                    //string str = System.Text.Encoding.Default.GetString(byteArray);

                    string转ASCII byte[]:
                    //byte[] byteArray = System.Text.Encoding.ASCII.GetBytes(str);

                    ASCII byte[]转string:
                    //string str = System.Text.Encoding.ASCII.GetString(byteArray);
                    // returnBytes =System.Text.Encoding.Default.GetBytes(a);
                    //returnBytes[i] = Convert.ToByte(a, 16);
                }
            }
            return returnBytes;
        }

        private static string StringToHexString(string s, Encoding encode)
        {
            byte[] b = encode.GetBytes(s);//按照指定编码将string编程字节数组
            string result = string.Empty;
            for (int i = 0; i < b.Length; i++)//逐字节变为16进制字符,以%隔开
            {
                result += "%" + Convert.ToString(b[i], 16);
            }
            return result;
        }




        #region PLC写 int float和bit数据
        // int 写
        private void button1_Click(object sender, EventArgs e)
        {
            TxCommand = "50 00 00 FF FF 03 00 12 00 10 00 01 14 00 00 960000 A8 0300 0C00 0D00 0E00";//96的十进制为150 写入D150 151 152 值 13 14 15
            TxCommand = TxCommand.Replace(" ", "");
            //十六进制转十进制
            byte[] bytes = new byte[TxCommand.Length / 2];
            for (int i = 0; i < TxCommand.Length; i += 2)
                bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);       //发送的命令转化成十进制
            Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令
            Client.GetStream().Write(bytes, 0, bytes.Length);
            while (!Client.GetStream().DataAvailable)
            {
                Application.DoEvents();
            }


            Client.GetStream().Read(InBuff, 0, InBuff.Length);
            RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
                                                       //D000 00FF FF03 0002 00 0000 D0 0000FFFF0300020000000

            //string[] hexbytes = new string[InBuff.Length];
            //hexbytes = byteToHexStr1(InBuff);            //转成字符串数组了
            SubHeader = RxResponse.Substring(18, 4);
            if (SubHeader == "0000")      //正常响应
            {
                MessageBox.Show("成功写入");
            }
        }

        // float 写
        private void button2_Click(object sender, EventArgs e)
        {
            //1.1在PLC里面 abcd  我们需要按dcba写入
            TxCommand = "50 00 00 FF FF 03 00 1000 10 00 01 14 00 00 B40000 A8 0200 CDCC 8C3F";//二进制   批量写  180      3F8C CCCD  ==  (REAL)CDCC 8C3F                                                 //    TxCommand = "50 00 00 FF FF 03 00 12 00 10 00 01 14 00 00 80 0000A8 02 00 CCCD 3DCC";//二进制D100-103    Y
            TxCommand = TxCommand.Replace(" ", "");
            //十六进制转十进制
            byte[] bytes = new byte[TxCommand.Length / 2];
            for (int i = 0; i < TxCommand.Length; i += 2)
                bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);       //发送的命令转化成十进制
            Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令

            Client.GetStream().Write(bytes, 0, bytes.Length);
            //等待以太网适配器的响应
            while (!Client.GetStream().DataAvailable)
            {
                Application.DoEvents();
            }

            Client.GetStream().Read(InBuff, 0, InBuff.Length);
            RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
            SubHeader = RxResponse.Substring(18, 4);
            if (SubHeader == "0000")      //正常响应
            {
                MessageBox.Show("成功写入");
            }
        }

        // bit 写
        private void button4_Click(object sender, EventArgs e)
        {
            double[] DregInt = new double[25536];

            //使用二进制 3E结构的命令,读出D100~D101(5个点)
            TxCommand = "50 00 00 FF FF03 00 1000 1000 0114 0100 640000 90 0800 00 00 11 11 ";//位批量写M100  8个
       
            TxCommand = TxCommand.Replace(" ", "");

            //十六进制转十进制
            byte[] bytes = new byte[TxCommand.Length / 2];
            for (int i = 0; i < TxCommand.Length; i += 2)
                bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);       //发送的命令转化成十进制
            Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令

            //等待以太网适配器的响应
            while (!Client.GetStream().DataAvailable)
            {
                Application.DoEvents();
            }
            Client.GetStream().Read(InBuff, 0, InBuff.Length);         //获取返回在命令放入InBuff中

            RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
            SubHeader = RxResponse.Substring(18, 4);
            if (SubHeader == "0000")      //正常响应
            {
                MessageBox.Show("成功写入");
            }
        }

        #endregion

        //int单值读
        private void button5_Click(object sender, EventArgs e)
        {
            double[] DregInt = new double[25536];
            TxCommand = "500000FFFF0300 0C00 1000 0104 00 00 **0000 A8 01 00";//二进制D100-103  A8代表的是D区  M区是90
            TxCommand = TxCommand.Replace(" ", "");  //删除空格
                                                     //偏移量处理。比如从D1开始读
            int offset = int.Parse(txtSread.Text);
            string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122


            OffsetNum = OffsetNum.ToString().PadLeft(4, '0');   //不够两个左边补0
            //高低位互换
            OffsetNum = OffsetNum.Substring(2, 2) + OffsetNum.Substring(0, 2);
            TxCommand = TxCommand.Remove(30, 4);
            TxCommand = TxCommand.Insert(30, OffsetNum);

            byte[] bytes = new byte[TxCommand.Length / 2];
            for (int i = 0; i < TxCommand.Length; i += 2)
                bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);

            Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令

            while (!Client.GetStream().DataAvailable)
            {
                Application.DoEvents();
            }
            Client.GetStream().Read(InBuff, 0, InBuff.Length);         //获取响应命令放入InBuff中

            RxResponse = byteToHexStr(InBuff);         //响应的命令转成一串十六进制字符串

            //直接字符串处理
            SubHeader = RxResponse.Substring(18, 4);  //截取结束代码
            if (SubHeader == "0000")      //正常响应
            {
                ResponseData = RxResponse.Substring(22, 4);
                int count = ResponseData.Length;
                for (int j = 0; j <= count / 4 - 1; j++)     //读五个整型的处理
                {
                    string DregStr = ResponseData.Substring(j * 4, 4);
                    DregStr = DregStr.Substring(2, 2) + DregStr.Substring(0, 2);  //高低位互换
                    DregInt[j] = Convert.ToInt32(DregStr, 16);        //十六进制转化为十进制  
                    listBox1.Items.Add(DregInt[j]);
                }
            }
            else
            {
                Temp = "Terminate Code" + SubHeader + "  Error Code";
                listBox1.Items.Insert(listBox1.Items.Count, Temp);
            }
        }

        //float单值读
        private void button6_Click(object sender, EventArgs e)
        {
            TxCommand = "500000FF FF 03 00 0C00 1000 0104 0000 680000 A8 02 00";//读四个字节
            TxCommand = TxCommand.Replace(" ", "");

            int offset = int.Parse(txtSread.Text);
            string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122


            OffsetNum = OffsetNum.ToString().PadLeft(4, '0');   //不够两个左边补0
            //高低位互换
            OffsetNum = OffsetNum.Substring(2, 2) + OffsetNum.Substring(0, 2);
            TxCommand = TxCommand.Remove(30, 4);
            TxCommand = TxCommand.Insert(30, OffsetNum);


            byte[] bytes = new byte[TxCommand.Length / 2];
            for (int i = 0; i < TxCommand.Length; i += 2)
                bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);

            Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令
            //等待以太网适配器的响应
            while (!Client.GetStream().DataAvailable)
            {
                Application.DoEvents();
            }
            Client.GetStream().Read(InBuff, 0, InBuff.Length);         //获取返回在命令放入InBuff中

            RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
            //D000 00 FFFF 0300 0A000000 CDCC CC3D CCCD 3DCC

            SubHeader = RxResponse.Substring(18, 4);
            if (SubHeader == "0000")      //正常响应
            {
                ResponseData = RxResponse.Substring(22, 8);
                int count = ResponseData.Length;
                byte[] bytef = new byte[4];
                for (int i = 0; i < 4; i++)
                {
                    string str = ResponseData.Substring(i * 2, 2);
                    bytef[i] = (byte)Convert.ToInt32(str, 16);
                }
                float fValue = BitConverter.ToSingle(bytef, 0);
                listBox1.Items.Add("D float" + ": " + fValue);
            }

        }

        //bit单值读
        private void button7_Click_1(object sender, EventArgs e)
        {
            TxCommand = "50 00 00 FF FF03 00 0C00 10 00 0104 0100 000000 90 01 00";   // 90-M  从M1开始

            TxCommand = TxCommand.Replace(" ", "");
            int offset = int.Parse(txtSread.Text);
            string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122


            OffsetNum = OffsetNum.ToString().PadLeft(4, '0');   //不够两个左边补0
            //高低位互换
            OffsetNum = OffsetNum.Substring(2, 2) + OffsetNum.Substring(0, 2);
            TxCommand = TxCommand.Remove(30, 4);
            TxCommand = TxCommand.Insert(30, OffsetNum);
            

            //十六进制转十进制 发送的命令转化成十进制
            byte[] bytes = new byte[TxCommand.Length / 2];
            for (int i = 0; i < TxCommand.Length; i += 2)
                bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);
            Client.GetStream().Write(bytes, 0, bytes.Length);
            while (!Client.GetStream().DataAvailable)
            {
                Application.DoEvents();
            }

            Client.GetStream().Read(InBuff, 0, InBuff.Length);         //获取返回在命令放入InBuff中

            RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了

            SubHeader = RxResponse.Substring(18, 4);
            if (SubHeader == "0000")      //正常响应
            {
                ResponseData = RxResponse.Substring(22, 1);
                listBox1.Items.Add("M : " + ResponseData);
            }
        }

        //字单值写 
        private void button9_Click(object sender, EventArgs e)
        {
            TxCommand = "50 00 00 FF FF 03 00 0E 00 10 00 01 14 00 00 ****00 A8 0100";//96的十进制为150 写入D150 151 152 值 13 14 15
            TxCommand = TxCommand.Replace(" ", "");

            //TxCommand = "50 00 00 FF FF 03 00 12 00 10 00 01 14 00 00 960000 A8 0300 0C00 0D00 0E00";//96的十进制为150 写入D150 151 152 值 13 14 15
            //TxCommand = "50 00 00 FF FF 03 00 12 00 10 00 01 14 00 00 960000 A8 0100";//0C00 0D00 0E00";//96的十进制为150 写入D150 151 152 值 13 14 15

            if (DataQuery(txtAddrWrite.Text, txtWriteContent.Text) == true)
            {
                //偏移量处理
                int offset = int.Parse(txtAddrWrite.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122

                OffsetNum = OffsetNum.ToString().PadLeft(4, '0');   //不够两个左边补0
                                                                    //高低位互换
                OffsetNum = OffsetNum.Substring(2, 2) + OffsetNum.Substring(0, 2);
                TxCommand = TxCommand.Remove(30, 4);
                TxCommand = TxCommand.Insert(30, OffsetNum);

                //写入内容处理
                int content = int.Parse(txtWriteContent.Text);
                string HexContent = string.Format("{0:X}", content);
                HexContent = HexContent.ToString().PadLeft(4, '0');   //不够两个左边补0
                HexContent = HexContent.Substring(2, 2) + HexContent.Substring(0, 2);//高低位调换
                TxCommand = String.Concat(TxCommand, HexContent);

                //十六进制转十进制
                byte[] bytes = new byte[TxCommand.Length / 2];
                for (int i = 0; i < TxCommand.Length; i += 2)
                    bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);       //发送的命令转化成十进制
                Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令
                Client.GetStream().Write(bytes, 0, bytes.Length);
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }

                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
                                                           //D000 00FF FF03 0002 00 0000 D0 0000FFFF0300020000000
                //string[] hexbytes = new string[InBuff.Length];
                //hexbytes = byteToHexStr1(InBuff);            //转成字符串数组了
                SubHeader = RxResponse.Substring(18, 4);
                if (SubHeader == "0000")      //正常响应
                {
                    MessageBox.Show("成功写入");
                }
            }
        }

        //float单值写
        private void button17_Click(object sender, EventArgs e)
        {
            //1.1在PLC里面 abcd  我们需要按dcba写入
            TxCommand = "50 00 00 FF FF 03 00 1000 10 00 01 14 00 00 B40000 A8 0200";//二进制   批量写  180      3F8C CCCD  ==  (REAL)CDCC 8C3F                                                 //    TxCommand = "50 00 00 FF FF 03 00 12 00 10 00 01 14 00 00 80 0000A8 02 00 CCCD 3DCC";//二进制D100-103    Y
            TxCommand = TxCommand.Replace(" ", "");

            byte[] HexValue = new byte[4];   //4个字节32位,1个字节8位FF
            string[] DregInt = new string[4];

            if (DataQuery(txtAddrWrite.Text, txtWriteContent.Text) == true)
            {
                //偏移量处理
                int offset = int.Parse(txtAddrWrite.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122


                OffsetNum = OffsetNum.ToString().PadLeft(4, '0');   //不够两个左边补0
                                                                    //高低位互换
                OffsetNum = OffsetNum.Substring(2, 2) + OffsetNum.Substring(0, 2);
                TxCommand = TxCommand.Remove(30, 4);
                TxCommand = TxCommand.Insert(30, OffsetNum);

                //写入内容处理
                float content1 = float.Parse(txtWriteContent.Text);
                var Hex_Value = FloatToHex(content1);      //转化为二进制
                HexValue = HexToFloat(Hex_Value);  //转化为16进制的数组
                for (int j = 0; j <= 3; j++)     //处理一个float
                {
                    int num = HexValue[j];
                    string HexNum = string.Format("{0:X}", num);   //大写对大写X x    
                    HexNum = HexNum.ToString().PadLeft(2, '0');   //不够两个左边补0
                    DregInt[j] = HexNum;   //大写对大写X x    
                }
                string content = "";

                //前四个和后四个换位置
                for (int i = 0; i <DregInt.Length; i++)
                {
                    content += DregInt[i];
                }
                TxCommand = String.Concat(TxCommand, content);

                //十六进制转十进制
                byte[] bytes = new byte[TxCommand.Length / 2];
              
                for (int i = 0; i < TxCommand.Length; i += 2)
                    bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);       //发送的命令转化成十进制
                Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令

                Client.GetStream().Write(bytes, 0, bytes.Length);
                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }

                Client.GetStream().Read(InBuff, 0, InBuff.Length);
                RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
                SubHeader = RxResponse.Substring(18, 4);
                if (SubHeader == "0000")      //正常响应
                {
                    MessageBox.Show("成功写入");
                }
            }
        }
        private static string FloatToHex(float value)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            StringBuilder stringBuffer = new StringBuilder();
            for (int i = 0; i < bytes.Length; i++)
            {
                if (i != 0)
                {
                    stringBuffer.Insert(0, " ");
                }
                string hex = Convert.ToString(bytes[i], 2);
                stringBuffer.Insert(0, hex);
                //位数不够补0
                for (int j = hex.Length; j < 8; j++)
                {
                    stringBuffer.Insert(0, "0");
                }
            }
            return stringBuffer.ToString();
        }
        private static byte[] HexToFloat(string str)
        {
            str = str.Replace(" ", string.Empty);
            if (str.Length != 32)
            {
                MessageBox.Show("数据长度错误");
                // return float.NaN;
            }
            byte[] intBuffer = new byte[4];
            //将二进制串按字节逆序化(一个字节八位)
            for (int i = 0; i < 4; i++)
            {
                string hex = str.Substring(24 - 8 * i, 8);
                intBuffer[i] = Convert.ToByte(hex, 2);
            }
            //return BitConverter.ToString(intBuffer, 0);
            return intBuffer;
        }

        //位单值写
        private void button16_Click(object sender, EventArgs e)
        {
            double[] DregInt = new double[25536];     ///14
            // TxCommand = "50 00 00 FF FF 03 00 3800 1000 0214 0000 0403 000000 A85005 010000 A87505 640000 904005 200000 9C8305 DC0500 A8 02123904 600100 9D 07267523 570400 90 75042504";//二进制D100-103    批量写
            //TxCommand = "50 00 00 FF FF 03 00 1100 1000 0214 0100 02 140000 90 11 2F0000 9D 01";//写入M20 1 左边补0  Y47 置1
            //TxCommand = "50 00 00 FF FF 03 00 0D00 1000 0114 0100 0A0000 90 0200 10 ";//写入M10 1 ,M11 0

            TxCommand = "50 00 00 FF FF 03 00 0C00 1000 0214 0100 01 **0000 90 0";//写入M20 1 左边补0
            TxCommand = TxCommand.Replace(" ", "");

            if (DataQuery(txtAddrWrite.Text, txtWriteContent.Text) == true)
            {
                //偏移量处理
                int offset = int.Parse(txtAddrWrite.Text);
                string OffsetNum = string.Format("{0:X}", offset);   //大写对大写X x     //122


                OffsetNum = OffsetNum.ToString().PadLeft(4, '0');   //不够两个左边补0
                                                                    //高低位互换
                OffsetNum = OffsetNum.Substring(2, 2) + OffsetNum.Substring(0, 2);
                TxCommand = TxCommand.Remove(32, 4);
                TxCommand = TxCommand.Insert(32, OffsetNum);


                //写入内容处理
                int content = int.Parse(txtWriteContent.Text);

                TxCommand = String.Concat(TxCommand, content);

                //十六进制转十进制
                byte[] bytes = new byte[TxCommand.Length / 2];
                for (int i = 0; i < TxCommand.Length; i += 2)
                    bytes[i / 2] = (byte)Convert.ToByte(TxCommand.Substring(i, 2), 16);       //发送的命令转化成十进制
                Client.GetStream().Write(bytes, 0, bytes.Length);      //发送命令

                //等待以太网适配器的响应
                while (!Client.GetStream().DataAvailable)
                {
                    Application.DoEvents();
                }
                Client.GetStream().Read(InBuff, 0, InBuff.Length);         //获取返回在命令放入InBuff中

                RxResponse = byteToHexStr(InBuff);         //转成一串十六进制的了
                SubHeader = RxResponse.Substring(18, 4);
                if (SubHeader == "0000")      //正常响应
                {
                    MessageBox.Show("成功写入");
                }
            }
        }
    }

}

 

 
  • 28
    点赞
  • 134
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
ilitek2510 是一款常见的 USB 触摸屏控制器芯片,Linux 平台下可以使用 HID 触摸屏驱动来支持 ilitek2510 触摸屏。 以下是步骤: 1. 确保系统已经加载了 hid-multitouch 驱动,可以使用以下命令来检查: ``` lsmod | grep hid_multitouch ``` 如果没有输出,则需要加载该驱动: ``` sudo modprobe hid-multitouch ``` 2. 连接 ilitek2510 触摸屏,并用以下命令来检测是否能够识别: ``` dmesg | grep input ``` 如果能够识别,则会输出如下信息: ``` input: ILITEK ILITEK-TP as /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.0/0003:22B8:2E82.0001/input/input3 hid-generic 0003:22B8:2E82.0001: input,hidraw0: USB HID v1.10 Pointer [ILITEK ILITEK-TP] on usb-0000:00:14.0-3/input0 ``` 其中,hidraw0 就是触摸屏的设备号。 3. 安装 xinput 工具,可以使用以下命令进行安装: ``` sudo apt-get install xinput ``` 4. 使用以下命令来调整触摸屏的参数: ``` xinput set-prop <device id> "Device Accel Velocity Scaling" <value> ``` 其中,device id 就是之前获取到的 hidraw 设备号,value 是一个浮点数,代表加速度的值。可以根据实际情况进行调整。 5. 如果需要在系统启动时自动加载 hid-multitouch 驱动和设置触摸屏参数,可以将以下脚本保存为 /etc/init.d/touchscreen,并授予可执行权限: ``` #!/bin/bash ### BEGIN INIT INFO # Provides: touchscreen # Required-Start: $local_fs $remote_fs $syslog # Required-Stop: $local_fs $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start touchscreen # Description: Enable support for ilitek2510 touchscreen on boot ### END INIT INFO case "$1" in start) modprobe hid-multitouch xinput set-prop <device id> "Device Accel Velocity Scaling" <value> ;; stop) ;; *) echo "Usage: $0 {start|stop}" exit 1 esac exit 0 ``` 然后使用以下命令将脚本添加到启动项中: ``` sudo update-rc.d touchscreen defaults ``` 以上就是在 Linux 平台下使用 ilitek2510 触摸屏的驱动方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值