一、关于cip协议

  cip通信是common industrial protocl(cip)的简称,它是一个点到点的面向对象协议,能够实现工业器件(传感器,执行器)之间的连接,和高等级的控制器之间的连接。目前,有3种网络devicenet,controlnet,ethernet/ip使用cip通信协议作为其上层网络协议,由odva组织统一管理,以确保其一致性和精确性。

二、ethernet/ip通信

  ethernet/ip(ethernet/industrial protocol),是一个工业级的通信网络,用于工业器件间高速的信息交换,这些器件包括简单的io器件(传感器),还有复杂的控制器(机器人,plc,焊机,过程控制器)。ethernet/ip使用cip(common industrial protocl),其使用ethernet和tcp/ip技术传送cip通信包,cip作为开放的应用层,位于ethernet和tcp/ip协议之上。

三、cip通信报文

1.注册会话id  

private byte[] registercmd = new byte[28]
{

  //——————————————————–header 24byte————————————-
  0x6f,0x00,//命令 2byte
  0x04,0x00,//header后面数据的长度 2byte
  0x00,0x00,0x00,0x00,//会话句柄 4byte
  0x00,0x00,0x00,0x00,//状态默认0 4byte
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//发送方描述默认0 8byte
  0x00,0x00,0x00,0x00,//选项默认0 4byte

       //——————————————————-commandspecificdata 指令指定数据 4byte

  0x01,0x00,//协议版本 2byte

  0x00,0x00,//选项标记 2byte
};

2.提取会话id-注册请求的应答报文

private byte[] refregistercmd = new byte[28] 
{

  //——————————————————–header 24byte————————————-
  0x6f,0x00,//命令 2byte
  0x04,0x00,//commandspecificdata的长度 2byte
  0x6b,0x01,0x01,0x00,//会话句柄 4byte 由plc生成
  0x00,0x00,0x00,0x00,//状态默认0 4byte
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//发送方描述默认0 8byte
  0x00,0x00,0x00,0x00,//选项默认0 4byte

   //——————————————————-commandspecificdata 指令指定数据 4byte

  0x01,0x00,//协议版本 2byte

  0x00,0x00,//选项标记 2byte
};

 

public byte[] sessionhandle=new byte[4]{0x6b,0x01,0x01,0x00};//从应答报文提取的会话id

后续读写plc的报文中,需要包含plc返回的会话id

 

 

3.读数据服务请求报文

 报文由三部分组成 header 24个字节 、commandspecificdata 16个字节、以及cip消息(由读取的标签生成)

 实例,读取单个标签名为 tag1的报文总长度为64个字节

private byte[] header = new byte[24]
{
  0x6f,0x00,//命令 2byte
  0x28,0x00,//长度 2byte(总长度-header的长度)=40 
  0x6b,0x01,0x01,0x00,//会话句柄 4byte
  0x00,0x00,0x00,0x00,//状态默认0 4byte
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//发送方描述默认0 8byte
  0x00,0x00,0x00,0x00,//选项默认0 4byte
};

private byte[] commandspecificdata = new byte[16]
{
  0x00,0x00,0x00,0x00,//接口句柄 cip默认为0x00000000 4byte
  0x01,0x00,//超时默认0x0001 4byte
  0x02,0x00,//项数默认0x0002 4byte
  0x00,0x00,//空地址项默认0x0000 2byte
  0x00,0x00,//长度默认0x0000 2byte
  0xb2,0x00,//未连接数据项默认为 0x00b2
  0x18,0x00,//后面数据包的长度 24个字节(总长度-header的长度-commandspecificdata的长度)
};

private byte[] cipmessage = new byte[24]
{

   0x52,0x02     //服务默认0x52  请求路径大小 默认2
  0x22,06,0×24,0x01,//请求路径 默认0x01240622 4byte
  0x0a,0xf0,//超时默认0xf00a 4byte
  0x0a,0x00,//cip指令长度  服务标识到服务命令指定数据的长度 
  0x4c,//服务标识固定为0x4c 1byte  
  0x03,// 节点长度 2byte  规律为 (标签名的长度+1/2)+1
  0x91,//扩展符号 默认为 0x91
  0x04,//标签名的长度

  0x54,0x41,0x47,0x31,//标签名 :tag1转换成ascii字节 当标签名的长度为奇数时,需要在末尾补0  比如tag转换成ascii为0x54,0x41,0x47,

     需要在末尾补0 变成 0x54,0x41,0x47,0

  0x01,0x00,//服务命令指定数据 默认为0x0001 

   0x01,0x00,0x01,0x00//最后一位是plc的槽号

};

plc回复报文:

6f0018006b01010000000000000000000000000000000000000000000100020000000000b200 08 00 cc 00 0000 c100  0000 

cc-服务标识 00-填充字节  0000-状态 0为正常  0800:cc-0000的长度  c100数据类型:bool   0000为数据false

 

 

 实例,读取多个标签名为 tag、tag1的报文总长度为86个字节

6f003e006b01010000000000000000000000000000000000000000000100020000000000b2002e005202200624010af020000a02200224010200060010004c0391035441470001004c03910454414731010001000100

header:6f003e006b01010000000000000000000000000000000000      24byte      

commandspecificdata: 00 00 00 00 0100020000000000b2002e00     16byte    

cipmessage:52 02  20062401  0af0 2000 0a 02  20022401  0200  0600 1000  4c0391 03 54414700 0100  4c039104544147310100  01000100

52-服务代码 02 -请求路径大小 20062401-请求路径  0af0超时   20 00 cip指令长度 (0a00之间的长度为32个字节)

0a-服务代码(多个标签) 02-请求路径大小  20022401请求路径 0200 标签的数量  0600 偏移量(初始值为:2+标签数量*2)

1000 偏移量 =标签服务长度+初始偏移量(有几个标签就有几个偏移量

4c 03 91 03 54414700 0100  标签tag  4c039104544147310100  标签tag1

plc回复报文:

6f0034006b01010000000000000000000000000000000000000000000100020000000000b20024008a000000020006001300cc000000d00005003232323232cc000000d00005003232323232    76byte

header:6f0034006b01010000000000000000000000000000000000  24byte

commandspecificdata:000000000100020000000000b2002400  16byte

cipmessage:8a00 0000 0200 0600 1300 cc 00 0000  d000 0500 3232323232  cc000000d00005003232323232

8a-多个标签   0000 -状态  0200-项数  0600-标签tag偏移量  1300-标签tag1偏移量  0000-状态0正常 d000-数据类型:string 

0500:字符串长度(字符串类型特有的)

3232323232-数据 “22222”:

目前常用的数据类型: c1-bool c2-sint c3-short c4-int  c7-ushort c8-uint  ca-float cb -double  d0-string

 

 

4.写入数据服务报文

实例,往标签名为:tag1 写入true  数据类型为 bool

写入报文:68byte

6f002c006b01010000000000000000000000000000000000 000000000100020000000000b2001c00 5202200624010af00e004d03910454414731c1000100010001000100      

header:6f002c006b01010000000000000000000000000000000000   24byte

commandspecificdata:000000000100020000000000b2001c00     16byte

cipmessage:52  02 20062401 0af0  0e00 4d 03 91 04 54414731 c100 0100 0100 01000100   28byte

52-服务标识     02请求路径大小  20062401-请求路径,默认   0af0-超时           0e00-cip指令长度(绿色部分的长度)

4d-写入标识     03(标签名的长度+1)/2+1   91-扩展符号    04-标签tag1的长度   54414731 -标签名的ascii表示

c100-数据类型    0100-默认项   0100-数据 true(2byte)          01000100 – 默认最后一位为plc槽号

plc回复报文:

6f0014006b0101 00000 00000000000000000000000000000 000000000100020000000000b2000400cd000000   44byte

header:6f0014006b01010000000000000000000000000000000000 24byte

 commandspecificdata:000000000100020000000000b2000400  16byte

cipmessage:cd 00 0000     cd-服务标识  00-填充字节  0000-状态好

注意:当写入字符串类型时,写入的数据长度为奇数时,需要在数据后填充一个字节0

 

5.扩展知识

  首先建立起tcp连接,cip通信端口默认为44818。tcp连接成功后,发送会话消息,获取四个字节的会话id,就可以正常读写了。

   header:6f0014006b0101 0000 000000000000000000000000000000 24byte

  0x0000:状态正常(在报文里低位在前高位在后)

  0x0001:发出了无效或不受支持的封装命令;

  0x0002:接收器中的内存资源不足,无法处理命令;

  0x0003:封装消息的数据部分中的数据形成不良或不正确;

  0x0004:reserved for legacy(ra);

  0x0064:向目标发送封装消息时,始发者使用了无效的会话句柄;

   0x0065:目标收到一个无效长度的信息

   0x0069:不支持的封装协议修订

    cipmessage:cd00 0000

  0x0000-成功

  0x0004-它没有正确生成或匹配标记不存在

  0x0005-引用的特定项(通常是实例)无法找到

  0x0006-请求的数据量不适合响应缓冲区。 发生了部分数据传输

  0x000a-尝试处理其中一个属性时发生错误

  0x0013-命令中没有提供足够的命令数据/参数来执行所请求的服务

  0x001c-与属性计数相比,提供的属性数量不足

  0x001e-此服务中的服务请求出错

  0x0020-命令中参数的数据类型与实际参数的数据类型不一致

  0x0026-ioi字长与处理的ioi数量不匹配