EIP
概述
EIP(EtherNet/IP)是一种基于标准以太网的工业通信协议,由 ODVA 组织维护。它使用 CIP(Common Industrial Protocol,通用工业协议)作为应用层协议,支持实时 I/O 数据和显式消息通信。本控制器通过 EtherNet/IP 与支持该协议的设备进行数据交互。
通讯模式
| 模式 | 说明 | 特点 |
|---|---|---|
| 显式消息(Explicit Messaging) | 基于 TCP,请求/应答模式 | 非实时,用于配置和诊断 |
| 隐式消息(Implicit Messaging) | 基于 UDP,生产者/消费者模式 | 实时,用于周期性 I/O 数据交换 |
CIP 协议层次
text
┌────────────────────────────┐
│ 应用对象 (CIP Objects) │
├────────────────────────────┤
│ CIP 通用工业协议 │
├───────────┬────────────────┤
│ 显式消息 │ 隐式消息(I/O) │
│ (TCP) │ (UDP) │
├───────────┴────────────────┤
│ TCP/IP 协议栈 │
├────────────────────────────┤
│ 以太网物理层 │
└────────────────────────────┘0x7360 上位机设置设备参数配置
参数列表
| 参数名 | 类型 | 必填 | 说明 | 取值范围 |
|---|---|---|---|---|
| type | int | 是 | 输入/输出路数 | 1 / 4 / 8 / 12 / 16 |
| grouptype | int | 是 | 组号的方式 | 0: 手填,1: 全局 int 类型变量,2: 全局 int 类型绑定变量 |
| group | int | 是 | 组号中的数字 | - |
| addtype | int | 是 | 数值存入的方式 | 0: 全局 int 类型变量,1: 全局 int 类型绑定变量,2: 全局 double 类型变量,3: 全局 double 类型绑定变量 |
| add | int | 是 | 数值存入的数字 | - |
| num | int | 是 | 编号 | 1-10: 输出,11-20: 输入 |
| value | - | 是 | 值 | - |
| able | bool | 是 | 使能开关 | true: 使能,false: 不使能 |
参数详解
- type:定义每路输入/输出的数据位宽。例如 type=16 时每路包含 16 个位信号
- grouptype:定义组号的来源方式。手填(0)直接使用 group 值;全局变量方式(1/2)从对应变量中读取组号
- addtype:定义数据存入的目标类型。int 变量存储整数,double 变量存储浮点数
- num:1~10 为输出信号,11~20 为输入信号,与外部设备的 I/O 映射对应
请求示例
json
{
"type": 4,
"grouptype": 1,
"group": 3,
"addtype": 2,
"add": 100,
"num": 5,
"value": 1,
"able": true
}响应
控制器响应并返回设备参数。响应数据结构与请求一致。
0x7361 上位机获取设备参数配置
请求参数
data: 无(发送空 JSON)
json
{}响应
控制器返回当前所有设备参数配置列表。
0x7362 上位机修改设备参数配置
参数格式同 0x7360。可修改已配置的设备参数,支持部分字段修改。
0x7363 上位机设置连接参数
参数列表
| 参数名 | 类型 | 必填 | 说明 | 取值范围 |
|---|---|---|---|---|
| enable | bool | 是 | 连接开关 | true: 打开连接开关,false: 关闭连接开关 |
| writenum | int | 是 | 输出(写入)数据长度 | [0, 256] |
| readnum | int | 是 | 输入(读取)数据长度 | [0, 256] |
| scancycle | int | 是 | 扫描周期(ms) | 建议 [1, 100] |
| outtimecycle | int | 是 | 超时周期(ms) | 应为扫描周期的倍数 |
| networkname | string | 是 | 选取的网口的名称 | 如 "eth0", "eth1" |
| writetype | int | 是 | 本机输出数据的类型 | 0: 全局 bool 类型变量,1: 全局 bool 类型绑定变量 |
| writeadd | int | 是 | 本机输出数据的起始地址 | 全局变量地址 |
| readtype | int | 是 | 本机输入数据的类型 | 0: 全局 bool 类型变量,1: 全局 bool 类型绑定变量 |
| readadd | int | 是 | 本机输入数据的起始地址 | 全局变量地址 |
参数详解
- writenum / readnum:定义输出/输入数据的长度(以 bool 为单位)。实际数据量 = writenum/readnum × 位宽
- scancycle:控制器获取/发送 EtherNet/IP 数据的周期,单位毫秒
- outtimecycle:通讯超时判定周期,若超过此时间未收到对端数据则判定超时。建议设置为 scancycle × 4
- networkname:指定使用的物理网口,需与设备实际连接的网络接口一致
请求示例
json
{
"enable": true,
"writenum": 64,
"readnum": 64,
"scancycle": 10,
"outtimecycle": 40,
"networkname": "eth0",
"writetype": 0,
"writeadd": 200,
"readtype": 0,
"readadd": 300
}0x7364 上位机获取连接参数配置
请求参数
data: 无(发送空 JSON)
json
{}响应
控制器返回当前的连接参数配置。数据结构与 0x7363 请求一致。
0x7365 上位机修改连接参数
参数格式同 0x7363。
0x7366 上位机向控制器获取连接状态
请求参数
data: 无(发送空 JSON)
json
{}响应
控制器返回当前的连接状态信息。
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| connected | bool | 连接状态,true-已连接,false-未连接 |
| linkSpeed | int | 链路速度(Mbps) |
| packetTx | int | 发送数据包计数 |
| packetRx | int | 接收数据包计数 |
| timeoutCount | int | 超时计数 |
| lastError | string | 最近一次错误描述 |
响应示例
json
{
"connected": true,
"linkSpeed": 100,
"packetTx": 15230,
"packetRx": 15128,
"timeoutCount": 0,
"lastError": ""
}0x7367 控制器返回读取数据的状态
控制器在周期性通讯中,主动推送输入数据的状态变化。
响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| num | int | 输入编号,范围 11-20 |
| value | int/bool/double | 输入当前值 |
| timestamp | int | 数据更新时间戳(ms) |
0x7368 读取数据的状态设置
上位机可主动设置输入数据的状态值(用于调试或模拟)。
参数列表
| 参数名 | 类型 | 必填 | 说明 | 取值范围 |
|---|---|---|---|---|
| num | int | 是 | 编号信息 | 0-9: 输出,10-19: 输入 |
| value | - | 是 | 设置的值 | 类型取决于 addtype 配置 |
请求示例
json
{
"num": 12,
"value": 1
}0x7369 读取数据的状态设置
控制输入数据是否随 EtherNet/IP 接收数据实时更新。
参数列表
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| state | bool | 是 | true: 输入数据跟随 EIP 接收数据实时更新,false: 冻结当前值 |
应用场景
- state=true:正常运行模式,输入数据实时反映外部设备状态
- state=false:调试/维护模式,冻结输入值,便于排查问题或手动模拟信号
请求示例
json
{
"state": false
}CIP 连接管理
连接建立流程
EtherNet/IP 使用 CIP 连接进行数据交换,连接建立过程如下:
text
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 上位机 │ │ 控制器 │ │ EIP 设备 │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
│ 0x7363 设置连接参数 │ │
│────────────────────>│ │
│ │ TCP 连接 │
│ │─────────────────────>│
│ │ 注册 Session │
│ │─────────────────────>│
│ │ Forward Open 请求 │
│ │─────────────────────>│
│ │ Forward Open 响应 │
│ │<─────────────────────│
│ │ │
│ │◄── 隐式消息(I/O) ──►│
│ │ (周期性数据交换) │连接类型
| 连接类型 | 传输方式 | 触发方式 | 典型用途 |
|---|---|---|---|
| Exclusive Owner | 点到点 | 周期 | 控制器独占控制 I/O 设备 |
| Input Only | 多播 | 周期 | 仅监听输入数据 |
| Listen Only | 多播 | 周期 | 监听其他连接的输出数据 |
Assembly 对象
Assembly 对象用于将离散 I/O 数据组合为一个数据块进行传输。
| Assembly 类型 | 实例 ID 范围 | 方向 | 说明 |
|---|---|---|---|
| Output Assembly | 100~199 | 本机 → 设备 | 输出数据集合 |
| Input Assembly | 200~299 | 设备 → 本机 | 输入数据集合 |
| Configuration Assembly | 300~399 | 本机 → 设备 | 配置数据集合 |
通讯状态监控
控制器主动上报状态变化
命令字: 0x736A
当 EtherNet/IP 连接状态发生变化时,控制器主动推送状态更新。
参数说明
| 字段 | 类型 | 描述 |
|---|---|---|
| status | int | 连接状态:0-空闲,1-连接中,2-运行中,3-超时,4-错误 |
| elapsedMs | int | 当前连接已持续时间(毫秒) |
| diagInfo | object | 诊断信息 |
diagInfo 说明
| 字段 | 类型 | 描述 |
|---|---|---|
| sessionHandle | int | CIP Session 句柄 |
| connectionId | int | CIP 连接 ID |
| rpi | int | 请求包间隔 RPI(ms) |
| openRetries | int | 连接打开重试次数 |
| watchDogTimeout | int | 看门狗超时次数 |
响应示例
json
{
"status": 2,
"elapsedMs": 3600000,
"diagInfo": {
"sessionHandle": 12345,
"connectionId": 67890,
"rpi": 10,
"openRetries": 0,
"watchDogTimeout": 0
}
}常见问题
连接问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 无法建立连接 | 网口选择错误 | 检查 networkname 是否与实际网口一致 |
| 无法建立连接 | 设备 IP 不在同一网段 | 配置控制器网口 IP 与设备同网段 |
| 数据不更新 | 扫描周期过大 | 减小 scancycle 值 |
| 数据不更新 | state 设为 false | 将 0x7369 的 state 设为 true |
| 频繁超时 | 网络负载过高 | 增大 outtimecycle,优化网络拓扑 |
| 频繁超时 | 网络设备故障 | 检查交换机、网线等硬件 |
| 数据错乱 | 数据长度不匹配 | 确认 writenum/readnum 与设备一致 |
| 数据错乱 | 字节序不一致 | 检查设备的字节序设置 |
性能优化建议
- 扫描周期建议根据实际 I/O 点数和网络条件设置,通常 5~50ms
- RPI(请求包间隔)应在
scancycle的基础上考虑网络延迟余量 - 对于纯监控类数据,可适当增大扫描周期以降低网络负载
- 使用
0x7366定期查询连接状态和通信统计,及时发现异常