什么是CIP
- CIP通信是Common Industrial Protocl(CIP)的简称,它是一个点到点的面向对象协议,
- 能够实现工业器件(传感器,执行器)之间的连接,和高等级的控制器之间的连接。
- 目前,有3种网络DeviceNet,ControlNet,EtherNet/IP使用CIP通信协议作为其上层网络协议,由ODVA组织统一管理,以确保其一致性和精确性。
CIP使用EtherNet时
首先建立起TCP连接,CIP通信端口默认为44818。TCP连接成功后,发送会话消息,获取四个字节的会话ID,就可以正常读写了。
连接PLC对应IP和这个端口(plc为TCP服务端)后上位机发送和收到的报文如下
# 发送的
6f 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
# 接收的
6F 00 00 00 00 00 00 00 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
提供的功能参考SYSMAC Compolet help文件
通信数据类型
Connect服务
Transaction服务
Disconnect服务
Abort服务
Sequence服务
通道参数数据类型
ReadChannelData服务
WriteChannelData服务
CIP协议报文
CIP协议最重要的特点是可以传输多种类型的数据,由于不同数据类型对传输的性能要求不一样,CIP协议报文可分为两类:显式报文和隐式报文。当CIP协议嵌入UDP协议用于发送隐式报文(Implicit(I/O)Message)。而CIP协议嵌入TCP协议用于发送显式报文(Explicit Message)。两种报文使用的封装协议不同,传输的消息类型也不同。CIP将应用对象之间的通讯关系抽象为连接,并与之相应制定了对象逻辑规范,使CIP协议可以不依赖与某一具体的网路硬件技术,用逻辑来定义连接的关系,在通信之前先建立连接获取唯一的标识符(Connection ID,CID),如果连接设计到双向的数据传输,就要分配两个CID。
显式报文针对组态信息、设备配置、故障诊断等非实时性信息,其优先级较低(包含解读该报文所需要的信息),通过点对点的报文在两个对象之间,以交互的方式进行传输。报文本身携带有关地址、数据类型和功能描述等相关内容,接受设备根据内容做出相应的处理,采用源/目的地址传送方式。在通信之前通过TCP协议获得标识符CID,之后进行数据报文传输。使用通信端口0XAF12f 。CIP显示报文连接如下图:
隐式报文用于节点之间传输实时I/O数据、实时互锁,优先级较高(隐式报文中不包含传送地址、数据类型标识和功能描述内容),全部作为有效数据,传输效率高,在报文头部有数据标识符,消费者根据标识符选择自己需要的内容,通过UDP协议将实时I/O消息传送到总线上。CIP隐式报文连接如下图:
CIP数据帧格式如下:
通信报文
// 注册会话ID
byte[] registerSessionCommand = new byte[]
{//--------------------------------------------------------Header 24byte-------------------------------------0x6F,0x00,//命令 2byte0x04,0x00,//Header后面数据的长度 2byte0x00,0x00,0x00,0x00,//会话句柄 4byte0x00,0x00,0x00,0x00,//状态默认0 4byte0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//发送方描述默认0 8byte0x00,0x00,0x00,0x00,//选项默认0 4byte//-------------------------------------------------------CommandSpecificData 指令指定数据 4byte0x01,0x00,//协议版本 2byte0x00,0x00,//选项标记 2byte
};//------------------3.读数据服务请求报文-------------------------
//报文由三部分组成 Header 24个字节 、CommandSpecificData 16个字节、以及CIP消息(由读取的标签生成)实例,
//读取单个标签名为 TAG1的报文总长度为64个字节
byte[] Header = new byte[24]
{0x6F,0x00,//命令 2byte0x28,0x00,//长度 2byte(总长度-Header的长度)=40 0x6B,0x01,0x01,0x00,//会话句柄 4byte0x00,0x00,0x00,0x00,//状态默认0 4byte0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//发送方描述默认0 8byte0x00,0x00,0x00,0x00,//选项默认0 4byte
};
byte[] CommandSpecificData = new byte[16]
{0x00,0x00,0x00,0x00,//接口句柄 CIP默认为0x00000000 4byte0x01,0x00,//超时默认0x0001 4byte0x02,0x00,//项数默认0x0002 4byte0x00,0x00,//空地址项默认0x0000 2byte0x00,0x00,//长度默认0x0000 2byte0xb2,0x00,//未连接数据项默认为 0x00b20x18,0x00,//后面数据包的长度 24个字节(总长度-Header的长度-CommandSpecificData的长度)
};
报文抓取
过滤报文可以用tcp.flags == 0x18来只查看CIP的报文数据,报文中左下部分是按照网络的五层架构从上到下排序显示的,右边则为收发的所有报文数据