一、關於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,0x24,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指令長度 (0A-00之間的長度為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數量不匹配
