使用CIP采集欧姆龙EtherNet/IP从入门到精通

使用CIP采集欧姆龙EtherNet/IP从入门到精通

本文将会从以下几个方面介绍

1.CIP是什么

2.EtherNet/IP通信是什么

3.CIP通信报文解析

4.使用CIP常用的方法和功能介绍(UCMM)

5.自己封装了一个类,只要知道标签名称,和数据类型即可读写数据

6.demo展示,支持多标签读取,支持带中文的标签读写

1.CIP是什么

CIP通信是Common Industrial Protocl(CIP)的简称,它是一个点到点的面向对象协议,能够实现工业器件(传感器,执行器)之间的连接,和高等级的控制器之间的连接。目前,有3种网络DeviceNet,ControlNet,EtherNet/IP使用CIP通信协议作为其上层网络协议,由ODVA组织统一管理,以确保其一致性和精确性。

2.EtherNet/IP通信是什么

EtherNet/IP(Ethernet/Industrial Protocol),是一个工业级的通信网络,用于工业器件间高速的信息交换,这些器件包括简单的IO器件(传感器),还有复杂的控制器(机器人,PLC,焊机,过程控制器)。EtherNet/IP使用CIP(Common Industrial Protocl),其使用EtherNet和TCP/IP技术传送CIP通信包,CIP作为开放的应用层,位于EtherNet和TCP/IP协议之上。

欧姆龙使用该协议,PLC端只要设置好数据类型和标签名称。上位机端根据数据类型和标签拼接报文即可实现读写。

3.CIP通信报文解析

这里参考:c#基于TCP/IP、CIP协议的欧姆龙PLC通信 - 非凡AFK - 博客园 (cnblogs.com)

欧姆龙NX系列EtherNet/IP通信 - 知乎 (zhihu.com) 这两篇文章即可。里面说的都很详细

4.使用CIP常用的方法和功能介绍(UCMM)

本质就是使用TcpClient连接,但是报文需要根据欧姆龙要求格式封装。

①首先用TcpClient建立连接

private void button1_Click(object sender, EventArgs e)//建立socket TCP通讯

{

client = new TcpClient();

//client1 = new UdpClient();

client.Connect(IPAddress.Parse("192.168.250.1"), 44818);

ns = client.GetStream();

if (client.Connected)

{

MessageBox.Show("服务器连接成功");

}

}

②获取会话句柄,msg400就是获取的会话句柄。无论读写报文的会话句柄都要替换成它

private void button3_Click(object sender, EventArgs e)//建立会话

{

if (client.Connected)

{

byte[] msg6 = new byte[28];

//string ch6 = null;

ns.Write(msg1, 0, msg1.Length);

ns.Read(msg6, 0, msg6.Length);

msg400 = msg6.Skip(4).Take(4).ToArray();//跳过4个,保留4个

// msg400 = msg400.Reverse().ToArray();//数组高低字节互换位置

Buffer.BlockCopy(msg400, 0, msg2, 4, 4);

Buffer.BlockCopy(msg400, 0, msg4, 4, 4);

Buffer.BlockCopy(msg400, 0, msgReal, 4, 4);

Buffer.BlockCopy(msg400, 0, msgint2, 4, 4);

string str1 = string.Join("", msg400.Select(b => string.Format("{0:X2} ", b)));//十六进制原义转换成字符串

//string str1 = BitConverter.ToString(msg400);

//uint PLC_FINS_NODE = System.BitConverter.ToUInt32(msg400, 0);

textBox1.Text = str1;

CIP_CONNECT = true;

}

}

③读取这个假设标签为SS,类型为Int16

byte[] msg2 = new byte[] { 0x6F, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x08, 0x00, 0x4C, 0x02, 0x91, 0x02, 0x53, 0x53, 0x01, 0x00};//读SS变量

private void Run()

{

(client.Connected&&CIP_CONNECT)

{

Thread.Sleep(1000);//暂停线程1000毫秒,相当于间隔1000毫秒读取数据

byte[] msg300 = new byte[2];

byte[] msg301 = new byte[2];

byte[] msg302 = new byte[2];

byte[] msg303 = new byte[2];

byte[] msg304 = new byte[2];

byte[] msg7 = new byte[70];

/*ushort read_channel1 = Convert.ToUInt16(numericUpDown1_read.Value);

msg300 = System.BitConverter.GetBytes(read_channel1);//数据转数组

msg301 = msg300.Reverse().ToArray();//数组高低字节互换位置

Buffer.BlockCopy(msg301, 0, msg2, 29, 2);//字节数组复制*/

ns.Write(msg2, 0, msg2.Length);

ns.Read(msg7, 0, msg7.Length);

//msg303 = msg7.Skip(28).Take(2).ToArray();

if (msg7[42] == 0X00)

{

msg304 = msg7.Skip(46).Take(2).ToArray();//跳过46个,保留2个

//msg304 = msg304.Reverse().ToArray();

short rdi = BitConverter.ToInt16(msg304, 0);

//string rds = string.Concat(msg304[0].ToString("X2"), msg304[1].ToString("X2")); //字符串连接

//[=int rd = Convert.ToInt16(msg304);

textBox3.Text = rdi.ToString();

}

}

}

④ 写值,假设标签依然是SS

byte[] msg4 = new byte[] { 0x6F, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x00, 0x0C, 0x00, 0x4D, 0x02, 0x91, 0x02, 0x53, 0x53, 0xC3, 0x00, 0x01, 0x00, 0x78, 0x56 };//写入SS变量

private void button6_Click(object sender, EventArgs e)//SS变量写数据

{

byte[] msg200 = new byte[2];

byte[] msg201 = new byte[2];

byte[] msg202 = new byte[2];

byte[] msg203 = new byte[2];

byte[] msg204 = new byte[50];

byte[] msg205 = new byte[1];

byte[] msg300 = new byte[2];

if (client.Connected && CIP_CONNECT)

{

short write_data = Convert.ToInt16(textBox4.Text, 10);//10表示字符串数据为十进制

//string wds = write_data.ToString("X4");

msg300 = System.BitConverter.GetBytes(write_data);//十进制数转十六进制数组

Buffer.BlockCopy(msg300, 0, msg4, 50, 2);

ns.Write(msg4, 0, msg4.Length);

ns.Read(msg204, 0, msg204.Length);

msg205 = msg204.Skip(42).Take(1).ToArray();

if (msg205[0] == 0X00)

{

MessageBox.Show("写入成功");

}

else

{

MessageBox.Show("写入失败");

}

}

}

⑤断开连接

private void button2_Click(object sender, EventArgs e)//关闭socket TCP通讯

{

client.Close();

if (!client.Connected)

{

MessageBox.Show("服务器连接关闭");

}

}

5.自己封装了一个类,只要知道标签名称,和数据类型即可读写数据

因为我觉得封装报文太麻烦了,所以我封装了一个类,在这里你读值时只要传入标签名称即可。写值时你需要传入标签和值即可。把繁琐的报文拼接同一封装。懒得拼接报文的可以直接使用该类

//读取

private void button10_Click(object sender, EventArgs e)

{

var a = pro_EtherNetIP.Read("w_int");

var a1 = pro_EtherNetIP.Read("w_real");

var a2 = pro_EtherNetIP.Read("w_string888");

var a3 = pro_EtherNetIP.Read("w_string");

var a4 = pro_EtherNetIP.Read("w_bool");

}

private void button11_Click(object sender, EventArgs e)

{

var b = pro_EtherNetIP.Write("w_int", 11);

var b1 = pro_EtherNetIP.Write("w_real", 11.8f);

var b2 = pro_EtherNetIP.Write("t_msH", 195.8);

//var b3 = pro_EtherNetIP.Write("w_string888", "bn5");

//var b4 = pro_EtherNetIP.Write("w_string", "as5");

var b5 = pro_EtherNetIP.Write("w_bool", false);

}

6.demo展示

下载链接点击

你也可以直接加我VX:z20240710. 加的时候备注CSDN。有偿

相关推荐

为什么檀香味没了(老山檀香手串不香了怎么办?!)
台灣7大最有人氣的網路購物平台【2025年版】
365投注入口

台灣7大最有人氣的網路購物平台【2025年版】

⌛ 07-06 👁️ 2757
苹果手机管家哪个好用
菠菜365哪个是真的

苹果手机管家哪个好用

⌛ 07-07 👁️ 4897
手机淘宝地址在哪里看
菠菜365哪个是真的

手机淘宝地址在哪里看

⌛ 07-07 👁️ 8270
ESTK新上线了四种实体卡,搬运个总结
菠菜365哪个是真的

ESTK新上线了四种实体卡,搬运个总结

⌛ 06-27 👁️ 8437
2025年电视盒子性价比榜单出炉:当贝H3、极光5S、创维T3