finsTCP
概述
FINS(Factory Interface Network Service)是欧姆龙(Omron)PLC 的专用通信协议,FINS/TCP 是通过 TCP/IP 网络封装 FINS 命令的通信方式。本控制器通过 FINS/TCP 协议与欧姆龙 PLC 进行数据交互,支持读写 PLC 的 DM 数据区。
协议栈结构
text
┌─────────────────────┐
│ FINS 命令/响应 │ ← 应用层
├─────────────────────┤
│ FINS 帧头 │ ← FINS Header (10字节)
├─────────────────────┤
│ TCP 封装 │ ← TCP/IP 传输层
└─────────────────────┘数据区映射
| 数据类型 | PLC 地址区 | 本机映射 | 说明 |
|---|---|---|---|
| DM 区 | DM0 ~ DM9999 | 全局变量区 | 数据存储区,支持读写 |
| 布尔量 | - | 全局布尔变量 | 本机与 PLC DM 区按位映射 |
1. 上位机设置 finsTCP 参数
命令字: 0x7340
参数列表
| 参数名 | 类型 | 说明 | 范围/格式 |
|---|---|---|---|
| IP | string | PLC 的 IP 地址 | 标准 IPv4 格式 |
| PLCReadAddress | string | PLC 读取首地址 | "DM" 开头 + 数字,范围 [1, 9999] |
| PLCWriteAddress | string | PLC 写入首地址 | "DM" 开头 + 数字,范围 [1, 9999] |
| craftNum | int | 工艺号 | 范围 [1, 9] |
| localReadAddress | int[] | 本机读取首地址列表 | 范围 [1, 990],第一位为全局布尔首地址,第二位为全局整型首地址 |
| localWriteAddress | int[] | 本机写入首地址列表 | 范围 [1, 990],第一位为全局布尔首地址,第二位为全局整型首地址 |
| port | int | 端口号 | 范围 [0, 65535],欧姆龙默认 9600 |
配置说明
- PLCReadAddress:控制器从 PLC 的此地址开始读取数据到本机
localReadAddress - PLCWriteAddress:控制器将本机
localWriteAddress的数据从此地址开始写入 PLC - localReadAddress[0]:全局布尔变量起始地址,localReadAddress[1]:全局整型变量起始地址
- 读写数据长度在 PLC 侧可配置,本机侧根据实际变量数量自动计算
请求示例
json
{
"IP": "192.168.1.10",
"PLCReadAddress": "DM2000",
"PLCWriteAddress": "DM1000",
"craftNum": 1,
"localReadAddress": [500, 500],
"localWriteAddress": [100, 100],
"port": 9600
}2. 上位机查询 finsTCP 参数
命令字: 0x7341
参数列表
| 参数名 | 类型 | 说明 | 范围 |
|---|---|---|---|
| craftNum | int | 查询的工艺号名称 | 范围 [1, 9] |
请求示例
json
{
"craftNum": 1
}3. 控制器回复上位机 finsTCP 参数
命令字: 0x7342
参数列表
| 参数名 | 类型 | 说明 | 范围/格式 |
|---|---|---|---|
| IP | string | IP 地址 | - |
| PLCReadAddress | string | PLC 读取首地址 | "DM" 开头 + 数字,范围 [1, 9999] |
| PLCWriteAddress | string | PLC 写入首地址 | "DM" 开头 + 数字,范围 [1, 9999] |
| craftNum | int | 工艺号 | 范围 [1, 9] |
| localReadAddress | int[] | 本机读取首地址列表 | 范围 [1, 990] |
| localWriteAddress | int[] | 本机写入首地址列表 | 范围 [1, 990] |
| port | int | 端口号 | 范围 [0, 65535] |
| status | int | 通讯状态 | 0-未连接,1-已连接 |
响应示例
json
{
"IP": "192.168.1.10",
"PLCReadAddress": "DM2000",
"PLCWriteAddress": "DM1000",
"craftNum": 1,
"localReadAddress": [500, 500],
"localWriteAddress": [100, 100],
"port": 9600,
"status": 0
}4. 上位机请求连接通讯
命令字: 0x7343
发送此命令后,控制器尝试与 PLC 建立 FINS/TCP 通信连接。
请求示例
json
{}连接流程
- 上位机发送连接命令
0x7343 - 控制器通过 TCP 三次握手与 PLC 建立连接
- 控制器发送 FINS 节点地址数据发送(CLIENT TO SERVER)命令注册节点
- 连接成功后控制器回复状态
0x7345(status=1) - 开始周期性地将本机数据写入 PLC,并从 PLC 读取数据
5. 上位机请求断开通讯
命令字: 0x7344
发送此命令后,控制器断开与 PLC 的 FINS/TCP 连接,停止数据交换。
请求示例
json
{}6. 控制器发送 finsTCP 通讯连接状态
命令字: 0x7345
参数列表
| 参数名 | 类型 | 说明 | 范围 |
|---|---|---|---|
| status | int | 通讯连接状态 | 0-未连接,1-已连接 |
响应示例
json
{
"status": 0
}7. 控制器发送 fins 打开的程序名称
命令字: 0x7346
参数列表
| 参数名 | 类型 | 说明 |
|---|---|---|
| programName | string | 打开的程序名称 |
响应示例
json
"AAA"8. FINS 协议帧格式
FINS 命令帧结构
FINS 命令帧由 FINS Header + FINS Command 组成,封装在 TCP 数据中。
| 字节偏移 | 长度(字节) | 字段名 | 说明 |
|---|---|---|---|
| 0 | 4 | ICF | 信息控制字段 |
| 4 | 4 | RSV | 保留字段(固定 0x00) |
| 8 | 2 | GCT | 网关计数(通常 0x02) |
| 10 | 1 | DNA | 目标网络地址(0x00=本地) |
| 11 | 1 | DA1 | 目标节点号 |
| 12 | 1 | DA2 | 目标单元号(0x00=CPU单元) |
| 13 | 1 | SNA | 源网络地址 |
| 14 | 1 | SA1 | 源节点号 |
| 15 | 1 | SA2 | 源单元号 |
| 16 | 2 | SID | 服务标识(请求/响应匹配用) |
| 18 | 2 | MRC | 主请求码 |
| 20 | 2 | SRC | 子请求码 |
| 22 | N | Data | 命令数据(变长) |
常用命令码
| MRC | SRC | 命令名称 | 说明 |
|---|---|---|---|
| 0x01 | 0x01 | MEMORY AREA READ | 读取指定存储区数据 |
| 0x01 | 0x02 | MEMORY AREA WRITE | 向指定存储区写入数据 |
| 0x01 | 0x03 | MEMORY AREA FILL | 填充存储区数据 |
| 0x01 | 0x04 | MULTIPLE MEMORY AREA READ | 批量读取多个存储区 |
| 0x02 | 0x01 | PARAMETER AREA READ | 读取参数区 |
| 0x02 | 0x02 | PARAMETER AREA WRITE | 写入参数区 |
| 0x04 | 0x01 | RUN | 切换到运行模式 |
| 0x04 | 0x02 | STOP | 切换到停止模式 |
| 0x05 | 0x01 | CPU UNIT DATA READ | 读取 CPU 单元数据 |
| 0x06 | 0x01 | CONNECTION DATA READ | 读取连接数据 |
存储区代码
FINS 协议通过存储区代码标识不同的数据区域:
| 代码 | 区域名称 | 说明 | 字节/字 |
|---|---|---|---|
| 0x82 | DM 区 | 数据存储器,16位字 | 2 字节/字 |
| 0xB0 | CIO 区 | 核心 I/O 区,位可访问 | 2 字节/字 |
| 0xB1 | WR 区 | 工作继电器区 | 2 字节/字 |
| 0xB2 | HR 区 | 保持继电器区 | 2 字节/字 |
| 0xB3 | AR 区 | 辅助继电器区 | 2 字节/字 |
9. 读写操作详解
上位机请求读取 PLC 数据
命令字: 0x7347
参数说明
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
| areaCode | int | 是 | 存储区代码,如 0x82 表示 DM 区 |
| startAddress | int | 是 | 读取起始地址(字地址) |
| wordCount | int | 是 | 读取字数,范围 [1, 512] |
| craftNum | int | 否 | 工艺号,范围 [1, 9];不填则使用当前连接工艺 |
请求示例
json
{
"areaCode": 130,
"startAddress": 2000,
"wordCount": 10,
"craftNum": 1
}控制器回复 PLC 读取数据
命令字: 0x7348
参数说明
| 字段 | 类型 | 描述 |
|---|---|---|
| areaCode | int | 存储区代码 |
| startAddress | int | 起始地址 |
| words | int[] | 读取到的字数据(每个字 0~65535) |
| status | int | 读取状态,0-成功,非0-失败 |
| errorMsg | string | 错误信息(失败时返回) |
响应示例
json
{
"areaCode": 130,
"startAddress": 2000,
"words": [100, 200, 300, 150, 250, 50, 75, 125, 500, 1000],
"status": 0
}上位机请求写入 PLC 数据
命令字: 0x7349
参数说明
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
| areaCode | int | 是 | 存储区代码,如 0x82 表示 DM 区 |
| startAddress | int | 是 | 写入起始地址(字地址) |
| words | int[] | 是 | 要写入的字数据,每个字范围 [0, 65535] |
| craftNum | int | 否 | 工艺号,范围 [1, 9] |
请求示例
json
{
"areaCode": 130,
"startAddress": 1000,
"words": [10, 20, 30, 40, 50],
"craftNum": 1
}控制器回复 PLC 写入结果
命令字: 0x734A
参数说明
| 字段 | 类型 | 描述 |
|---|---|---|
| areaCode | int | 存储区代码 |
| startAddress | int | 起始地址 |
| status | int | 写入状态,0-成功,非0-失败 |
| errorMsg | string | 错误信息(失败时返回) |
响应示例
json
{
"areaCode": 130,
"startAddress": 1000,
"status": 0
}10. 通讯错误码
| 错误码 | 说明 | 处理建议 |
|---|---|---|
| 0x0000 | 正常完成 | - |
| 0x0101 | 连接失败(TCP 层) | 检查 IP、端口和网络连通性 |
| 0x0102 | 节点注册失败 | 检查 PLC 的 FINS 节点地址配置 |
| 0x0201 | 不支持的存储区代码 | 确认 areaCode 正确 |
| 0x0202 | 地址超出范围 | 确认 startAddress 和 wordCount 在有效范围 |
| 0x0203 | 数据长度错误 | 确认 words 数组长度与 wordCount 一致 |
| 0x0301 | PLC 处于不可操作状态 | 将 PLC 切换到监视/运行模式 |
| 0x0302 | 写入被禁止 | 检查 PLC 的写保护设置 |
| 0x0401 | 命令超时 | 增大超时时间或检查网络负载 |
| 0x0402 | 响应格式异常 | 检查 PLC 固件版本兼容性 |
11. 通讯时序
典型数据交互周期
text
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 上位机 │ │ 控制器 │ │ PLC │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
│ 0x7343 连接请求 │ │
│───────────────────>│ │
│ │ TCP Connect │
│ │───────────────────>│
│ │ FINS Node Reg │
│ │───────────────────>│
│ 0x7345 连接成功 │ │
│<───────────────────│ │
│ │ │
│ │◄──── 循环读写 ────►│
│ │ (DM 区周期交换) │
│ │ │周期性数据交换
连接建立后,控制器以固定周期执行以下数据交换:
- 写入阶段:将
localWriteAddress的全局变量数据写入 PLC 的PLCWriteAddress起始的 DM 区 - 读取阶段:从 PLC 的
PLCReadAddress起始的 DM 区读取数据到localReadAddress的全局变量
布尔量以位为单位映射到 DM 区的对应位,整型以 16 位字为单位映射。
12. 常见问题
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 连接不上 PLC | IP 地址错误 | 确认 PLC IP 地址,可用 ping 测试 |
| 连接不上 PLC | 端口错误 | 欧姆龙 PLC 默认端口为 9600 |
| 连接不上 PLC | PLC 不在同一网段 | 检查网络配置 |
| 读写数据不正确 | 地址偏移 | 确认 DM 起始地址与 PLC 程序一致 |
| 读写数据不正确 | 数据长度不匹配 | 核对本机变量数量和 PLC 数据长度配置 |
| 通讯中断 | 网络故障 | 检查网络设备状态,查看 0x7345 状态码 |
| 通讯中断 | PLC 模式变更 | 确认 PLC 处于监视/运行模式 |