C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试

到目前为止,还没有网上有哪个文章有我如此的报文分析,操作实例,一大批都是抄来抄去,没有截图,没有说明,没有实例,有卵用呀,仅以此文章献给最爱的粉丝,希望对各位大师有些启示。

原创真的不容易,走过路过不要错过,点赞关注收藏又圈粉,共同致富。

原创真的不容易,走过路过不要错过,点赞关注收藏又圈粉,共同致富。

原创真的不容易,走过路过不要错过,点赞关注收藏又圈粉,共同致富。 

1、A-1E协议回顾

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第1张图片C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第2张图片C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第3张图片

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第4张图片 

上节文章完成了下面几项操作:

1、读取D100地址开始的2个int类型数据

2、 通过A1E进行D102的双字 DWord(Float) 读取,即读取float类型--4Byte 

3、通过A1E进行位的读取M16,M区的地址要转换成16进制,即读取bool类型数据

4、通过A1E进行字的写入,即向 D20,D21写入34,45

5、通过A1E向 D30 写入一个Float数据24.5,一个float占4个字节 

通过5个操作实例掌握了报文的结构,发送和接收都有报文的结构,但那是通过工具软件“网络调试助手”实现的,这节来通过C#代码组成报文结构并测试效果,需要用到vs2022开发工具,字节数组,socket通信等知识。

2、启动mc服务器

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第5张图片

3、创建项目方案

打开VS2022,创建控制台项目

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第6张图片

 C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第7张图片

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第8张图片

4、报文组装与测试

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第9张图片

1、读取D100地址开始的2个int类型数据

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第10张图片

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第11张图片

发送:01 FF 0A 00 64 00 00 00 20 44 02 00 

响应:81 00 19 00 26 00 

 

2、 通过A1E进行D102的双字 DWord(Float) 读取,即读取float类型--4Byte 

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第12张图片

发送:01 FF 0A 00 66 00 00 00 20 44 04 00  

接收:81 00 33 33 35 42 00 00 00 00  

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第13张图片

3、通过A1E进行位的读取M16,M区的地址要转换成16进制,即读取bool类型数据

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第14张图片

发送:00 FF 0A 00 10 00 00 00 20 4D 01 00 

接收:80 00 10  

 C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第15张图片

4、通过A1E进行字的写入,即向 D20,D21写入34,45

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第16张图片

发送:03 FF 0A 00 14 00 00 00 20 44 02 00 22 00 2D 00  

接收:83 00 

 C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第17张图片

5、通过A1E向 D30 写入一个Float数据24.5,一个float占4个字节 

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第18张图片

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第19张图片

发送:03 FF 0A 00 1E 00 00 00 20 44 02 00 00 00 C4 41 

接收:83 00 

6、完整代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace MitSUBISHI.MCProtocol.Test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            MCTestA1E();  
            Console.WriteLine("执行完成!");
            Console.ReadKey();
        }

        private static void MCTestA1E()
        {
            // 连接
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Connect("192.168.1.3", 6000);

            #region 1、通过A1E进行D100地址按字进行读取2个,即读取int类型  

            //int len = 2;
            //byte[] bytes = new byte[] {
            //        0x01,
            //        0xFF,0x0A,0x00,
            //        0x64,0x00,0x00,0x00, // 起始地址
            //        0x20,0x44, // 存储区 
            //        (byte)(len%256),
            //        (byte)(len/256%256) // 读取长度
            //    };
            //socket.Send(bytes);
            //byte[] respBytes = new byte[len * 2 + 2];
            //socket.Receive(respBytes);

            //for (int i = 2; i < respBytes.Length; i++)
            //{
            //    //每2个字节一组
            //    byte[] temp = new byte[2];
            //    temp[0] = respBytes[i];
            //    temp[1] = respBytes[++i];
            //    Console.WriteLine(BitConverter.ToInt16(temp, 0));//字节数组转换成int16数据
            //}

            #endregion

            #region 2、通过A1E进行D102的双字 DWord(Float) 读取,即读取float类型--4Byte 

            //int len = 2;
            //byte[] bytes = new byte[] {
            //    0x01,//0x01代表按批量字
            //    0xFF,0x0A,0x00,
            //    0x66,0x00,0x00,0x00, // 起始地址
            //    0x20,0x44, // 存储区 
            //    (byte)(len*2%256),
            //    (byte)(len*2/256%256) // 读取长度
            //};
            //socket.Send(bytes);
            //byte[] respBytes = new byte[len * 2 * 2 + 2];
            //socket.Receive(respBytes);

            //for (int i = 2; i < respBytes.Length; i++)
            //{
            //    //每4个字节一组
            //    byte[] temp = new byte[4];
            //    temp[0] = respBytes[i];
            //    temp[1] = respBytes[++i];
            //    temp[2] = respBytes[++i];
            //    temp[3] = respBytes[++i];
            //    Console.WriteLine(BitConverter.ToSingle(temp, 0));//字节数组转换成float数据
            //}
            #endregion

            #region 3、通过A1E进行位的读取M16,M区的地址要转换成16进制,即读取bool类型数据

            //int len = 1;
            //byte[] bytes = new byte[] {
            //    0x00,  // 代表批量位
            //    0xFF,0x0A,0x00,
            //    0x10,0x00,0x00,0x00, // 起始地址
            //    0x20,0x4D, // 存储区 
            //    (byte)(len%256),
            //    (byte)(len/256%256) // 读取长度
            //};

            //socket.Send(bytes);
             最终的数据长度是多少个字节  
            //int readLen = (int)Math.Ceiling(len * 1.0 / 2);
            //byte[] respBytes = new byte[readLen + 2];
            //socket.Receive(respBytes);
            //string binaryStr = "";
            //List tempList = new List();
            //for (int i = 2; i < respBytes.Length; i++)
            //{
            //    binaryStr = Convert.ToString(respBytes[i], 2).PadLeft(8, '0');
            //    // 每转换一次可以拿两个位信息
            //    tempList.Add(binaryStr.Substring(0, 4));
            //    tempList.Add(binaryStr.Substring(4));
            //}
            //for (int i = 0; i < len; i++)
            //{
            //    Console.WriteLine(tempList[i] == "0001");
            //}

            #endregion

            #region 4、通过A1E进行字的写入,即向 D20,D21写入34,45
            //int len = 2;
            //short v1 = 34, v2 = 45;
            //byte[] bytes = new byte[] {
            //    0x03,  // 代表批量位字
            //    0xFF,0x0A,0x00,
            //    0x14,0x00,0x00,0x00, // 起始地址
            //    0x20,0x44, // 存储区 
            //    // 写入长度
            //    (byte)(len%256),//低位
            //    (byte)(len/256%256), //高位
            //    //第一个数据
            //    (byte)(v1%256),//低位
            //    (byte)(v1/256%256),//高位
            //    //第二个数据
            //    (byte)(v2%256),
            //    (byte)(v2/256%256)
            //};

            //socket.Send(bytes);
            //int readLen = (int)Math.Ceiling(len * 1.0 / 2);
            //byte[] respBytes = new byte[2];
            //socket.Receive(respBytes);
            //var obj = respBytes;
            //if (Convert.ToInt16(respBytes[1]) == 0)
            //{
            //    Console.WriteLine("写入成功");
            //}
            #endregion

            #region 5、通过A1E向 D30 写入一个Float数据24.5,一个float占4个字节

            int len = 1;   // 一个值是4个字节    2个寄存器
            float value = 24.5f;

            byte[] bytes = new byte[] {
                0x03,  // 代表批量字
                0xFF,0x0A,0x00,
                0x1E,0x00,0x00,0x00, // 起始地址
                0x20,0x44, // 存储区 
                (byte)(len*2%256),
                (byte)(len*2/256%256), // 写入长度
                BitConverter.GetBytes(value)[0],
                BitConverter.GetBytes(value)[1],
                BitConverter.GetBytes(value)[2],
                BitConverter.GetBytes(value)[3]
            };

            socket.Send(bytes);

            int readLen = (int)Math.Ceiling(len * 1.0 / 2);
            byte[] respBytes = new byte[2];
            socket.Receive(respBytes);
            var obj = respBytes;
            if (Convert.ToInt16(respBytes[1]) == 0)
            {
                Console.WriteLine("写入成功");
            }

            #endregion
        }
    }
}

5、小结

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第20张图片

C#上位机与三菱PLC的通信04--MC协议之A-1E报文测试_第21张图片 

到目前为止,还没有网上有哪个文章有我如此的报文分析,操作实例,一大批都是抄来抄去,仅以此文章献给最爱的粉丝,希望对各位大师有些启示。

原创真的不容易,走过路过不要错过,点赞关注收藏又圈粉,共同致富。

原创真的不容易,走过路过不要错过,点赞关注收藏又圈粉,共同致富。

原创真的不容易,走过路过不要错过,点赞关注收藏又圈粉,共同致富。 

 

你可能感兴趣的:(C#上位机开发笔记,c#,MC协议,A-1E报文,三菱PLC,C#与三菱PLC,三菱MC协议分析)