• C#与三菱FX2NPLC的RS232接口通讯(Read)


    在项目中有一台FX2N系列的PLC需要通过C#232协议的方式读写数据,查找了很多资料,都没有具体的C#的读写方法,因此我记录一下详细的操作步骤。

    1. 要知道连接PLC的通讯协议,波特率,奇偶校验,数据位等信息的获取,请自行查询。我使用的测试PLC协议为 9600 7 E 1
    2. 读数据命令格式

    02H 30H 起始地址1 读取长度 03H 校验1 校验2

    说明:

    02H代表命令开始

    30H代表读操作

    03H代表命令结束

    起始地址计算方法:

     

    ex: 读D123,D124两个点的数据

    D123对应地址计算方法为:

    123*2=246

    246对应十六进制为F6H

    Address=F6H+1000H=10F6H

    故实际地址未 31H 30H 46H 36H

    加入需要读取D123,D124两个地址,因为D的长度为2,所以读取长度应该为2*2=4

    故长度为 30H 34H

    校验计算方法为:

    02H后道03H为止(包含03H)相加,然后取最后两位得到校验数据

    02H 30H 31H 30H 46H 36H 30H 34H 03H 校验1 校验2

    30H+31H+30H+46H+36H+30H+34H+03H=174H

    故校验1=37H 校验2=34H

    所以,完整的命令如下

    02H 30H 31H 30H 46H 36H 30H 34H 03H 37H 34H

    示例,下面是获取D120-D125 六个点的数据

    命令为:

    120*2=240 对应十六进制为F0

    F0+1000=10F0

    长度为6*2=12所以为C对应命令为30H 43H

    校验位为30H+31H+30H+46H+30H+30H+43H+03H=17D 故校验位为37H 44H

    02H 30H 31H 30H 46H 30H 30H 43H 03H 37H 44H

    返回数据格式为:

    02H 数据1.... 03H 校验1 校验2

    执行上面的示例命令得到下面返回

    02 32 30 30 30 43 38 30 31

    34 43 30 30 32 32 30 30 34 31 30 30 35 36 30 30 03 43 43

    解析方式:

    每个数据由4个字节构成

    例如上面返回总共6个数据,所以占24个字节

    前四个字节32 30 30 30 构成第一个数据

    数据构成规格为L1L2H1H2所以实际数据应该是30 30 32 30所以实际数据的十六进制为20对应十进制为32

    同理第二个数据为43 38 30 31实际数据应为01C8,十六进制1C8对应十进制456

     

    下面是C#读取数据的源代码:

    232协议配置

    SerialPort sp=new SerialPort();

    sp.DataReceived += Sp_DataReceived;

    sp.PortName = "COM5";

    sp.DataBits = 7;

    sp.BaudRate = 9600;

    sp.Parity = Parity.Even;

    sp.StopBits = StopBits.One;

    sp.Open();

    命令解析代码

     byte[] wD = new byte[11];

                wD.Initialize();

                wD[0]= 0x02;//起始位

                wD[1] = 0x30;//30读,31写

                if (txtStartAddress.Text.StartsWith("D"))

                {

                    int addSou = Convert.ToInt32(txtStartAddress.Text.Substring(1));

                    if (addSou > 9999 || addSou < 0)

                    {

                        MessageBox.Show("地址范围为0-9999");

                        return;

                    }

                    addSou *= 2;

                    int addBase = 4096;//1000H对应10进制为4096

                    int startAdd = addBase + addSou;

                    string strAdd = startAdd.ToString("x8").TrimStart('0').ToUpper().PadLeft(4, '0');

                    wD[2] = Convert.ToByte(strAdd[0]);

                    wD[3] = Convert.ToByte(strAdd[1]);

                    wD[4] = Convert.ToByte(strAdd[2]);

                    wD[5] = Convert.ToByte(strAdd[3]);

                }

                int length = Convert.ToInt32(txtLength.Text);

                length *= 2;

                string strLen = length.ToString("x8").TrimStart('0').ToUpper().PadLeft(2, '0');

                wD[6] = Convert.ToByte(strLen[0]);

                wD[7] = Convert.ToByte(strLen[1]);

                wD[8] = 0x03;//结束位

                int total = 0;

                for (int i = 1; i < 9; i++)

                {

                    total += Convert.ToInt32(wD[i].ToString());

                }

                string cal = total.ToString("x8").TrimStart('0').ToUpper();

                cal = cal.Substring(cal.Length - 2).PadLeft(2, '0');

                wD[9] = Convert.ToByte(cal[0]);

                wD[10] = Convert.ToByte(cal[1]);

                sp.Write(wD, 0, 11);

    数据解析代码

      byte[] buffer = new byte[sp.BytesToRead];

     sp.Read(buffer, 0, buffer.Length);

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

    {

         //返回数据的格式为L1L2H1H2,所以下面需要转换顺序

         string d1 = Encoding.ASCII.GetString(buffer, i * 4 + 3, 1);

         string d2 = Encoding.ASCII.GetString(buffer, i * 4 + 4, 1);

         string d3 = Encoding.ASCII.GetString(buffer, i * 4 + 1, 1);

         string d4 = Encoding.ASCII.GetString(buffer, i * 4 + 2, 1);

         string temp = string.Format("{0}{1}{2}{3}", d1, d2, d3, d4);

         string result = int.Parse(temp, NumberStyles.HexNumber).ToString();

    }

  • 相关阅读:
    div在父集高度未知的情况下垂直居中的方法
    固比固布局 圣杯布局 css实现传统手机app布局
    img标签的onerror事件
    vue中的swiper element ui
    前后端分离跨域 关于前后端分离开发环境下的跨域访问问题(angular proxy=>nginx )
    自己开发的网页在跳转至微信公众号文章后,点击微信的返回,无法返回原网页
    关于audio元素在实际项目中遇到的问题总结
    移动端HTML5<video>视频播放优化实践
    数据类型转换
    穿越宇宙的邀请函——镜像图片技巧
  • 原文地址:https://www.cnblogs.com/ckym/p/15720053.html
Copyright © 2020-2023  润新知