Slave 属性与方法
通过 master.getSlave(n) 访问(1-based 索引)或 master.Slaves() 获取列表。
属性
| 类别 | 属性 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 基本标识 | SlaveNum | short (public final) | 只读 | 从站编号(1-based,不变值) |
| MasterIndex | short (public final) | 只读 | 所属主站编号(不变值) | |
| Name() | String | 只读 | 设备名称(从 EEPROM 读取) | |
| DriveName() | String | 只读 | 驱动名称(从 SDO 0x1008 读取) | |
| 设备信息 | VendorId() | int | 只读 | 制造商 ID(从 SII EEPROM 读取) |
| VendorName() | String | 只读 | 制造商名称(从 ESI 文件读取) | |
| ProductId() | int | 只读 | 产品 ID | |
| RevId() / Revision() | int | 只读 | 修订版本号 | |
| SerialNumber() | int | 只读 | 序列号(从 SII EEPROM 读取) | |
| Dtype() | short | 只读 | 设备类型标识(可转换为 EcDeviceType) | |
| HasMDP() | boolean | 只读 | 是否支持模块化设备配置文件(ETG.5001) | |
| BlockLRW() | boolean | 只读 | 逻辑读写操作阻止标志 | |
| 地址 | ConfigAddr() | short | 只读 | 物理配置地址 |
| AliasAddress() | short | 只读 | 别名地址 | |
| Index() | int | 只读 | 从站索引(SlaveNum 别名) | |
| 状态 | State() | EcState | 只读 | 从站当前 EtherCAT 状态 |
| ErrorCode() | EcALState | 只读 | AL Status Code 错误码 | |
| IsLost() | boolean | 只读 | 从站是否丢失(断开连接) | |
| 拓扑 | TopologyByte() | byte | 只读 | 拓扑类型 (0=无链接, 1=端点, 2=中间, 3=分支, 4=交叉) |
| ParentStation() | int | 只读 | 父从站的站地址 | |
| ParentPort() | byte | 只读 | 父端口号 | |
| EntryPort() | byte | 只读 | 入口端口号 | |
| ActivePorts() | byte | 只读 | 激活端口位掩码 | |
| PhysicalType() | byte | 只读 | 物理端口类型 | |
| PDO 数据 | Ibits() / Obits() | short | 只读 | 输入/输出数据位数 |
| Ibytes() / Obytes() | int | 只读 | 输入/输出数据字节数 | |
| Ioffset() / Ooffset() | int | 只读 | 输入/输出在过程数据中的偏移 | |
| Istartbit() / Ostartbit() | byte | 只读 | 输入/输出起始位 | |
| ESI/配置 | HasEsi() | boolean | 只读 | 是否已加载 ESI 文件 |
| EsiVersion() | String | 只读 | ESI 版本号 | |
| EEPROM | Eep8ByteAddressing() | boolean | 只读 | EEPROM 寻址模式(true=8字节, false=4字节) |
| EepPDI() | byte | 只读 | 物理设备接口(PDI)类型 | |
| EbusCurrent() | short | 只读 | E-bus 电流消耗(mA) | |
| SIIindex() | int | 只读 | SII EEPROM 配置索引 | |
| 邮箱 | MbxProto() | short | 只读 | 支持的邮箱协议类型(MailboxType 位掩码) |
| MbxLength() | short | 只读 | 邮箱发送缓冲区大小 | |
| MbxReadLength() | short | 只读 | 邮箱接收缓冲区大小 | |
| MbxReadOffset() / MbxWriteOffset() | short | 只读 | 邮箱读/写偏移 | |
| MbxCount() | byte | 只读 | 邮箱协议计数器 | |
| 协议详情 | CoEdetails() | byte | 只读 | CoE 协议功能标志(SDO/PDO Assign/Complete Access 等) |
| EoEdetails() | byte | 只读 | EoE 协议功能标志(发送帧/接收帧/IP 参数等) | |
| FoEdetails() | byte | 只读 | FoE 协议详情(来自 SII EEPROM) | |
| SoEdetails() | byte | 只读 | SoE 协议详情(来自 SII EEPROM) | |
| FMMU | FMMU0Function() | byte | 只读 | FMMU0 功能类型(bit 0=输出, bit 1=输入) |
| FMMU1Function() | byte | 只读 | FMMU1 功能类型 | |
| FMMU2Function() | byte | 只读 | FMMU2 功能类型 | |
| FMMU3Function() | byte | 只读 | FMMU3 功能类型 | |
| DC | HasDC() | boolean | 只读 | 是否支持 DC,详见 DC 同步 |
| DCActive() | int | 只读 | DC 激活状态(0=禁用, 非0=已激活),详见 DC 同步 | |
| DCCycle0() / DCCycle1() | int | 只读 | SYNC0/SYNC1 周期(纳秒),详见 DC 同步 | |
| DCShift() | int | 只读 | 相位偏移(纳秒),详见 DC 同步 | |
| PDelay() | int | 只读 | 帧从主站到达此从站的传播延迟(纳秒),详见 DC 同步 | |
| DCNext() | int | 只读 | DC 下一个从站索引 | |
| DCPrevious() | int | 只读 | DC 上一个从站索引 | |
| DCReceiveTimeA/B/C/D() | int | 只读 | 端口 A/B/C/D 接收时间(纳秒) | |
| 拓扑扩展 | SupportsFrameRepeat() / SupportsFrameRepeat(boolean) | boolean | 读写 | 是否支持帧重复功能(ETG.1500 5.4.3) |
| 冗余 | RedundancyActivated() | boolean | 只读 | 冗余是否激活 |
| PrimaryLinkBroken() | boolean | 只读 | 主线路断路 | |
| SecondaryLinkBroken() | boolean | 只读 | 冗余线路断路 | |
| 配置 | Group() / Group(byte) | byte | 读写 | 从站分组号(0-7,0=默认组,必须在 SAFE_OP 前设置),详见 从站分组 |
| IsOptional() / IsOptional(boolean) | boolean | 读写 | 可选从站标记,缺席时不影响 WKC 检查、不触发组离线告警(必须在 OP 前设置) |
EcDeviceType 枚举
public enum EcDeviceType {
UNDEFINED(0), // 未定义
STATIC(1), // 静态设备,无 IO 映射,如 EK1100 耦合器
INPUT_NO_MAILBOX(2), // 输入设备(无邮箱)
OUTPUT_NO_MAILBOX(3), // 输出设备(无邮箱)
INPUT_WITH_MAILBOX(4), // 输入设备(有邮箱)
OUTPUT_WITH_MAILBOX(5), // 输出设备(有邮箱)
IO_NO_MAILBOX(6), // 输入输出设备(无邮箱)
IO_WITH_MAILBOX(7); // 输入输出设备(有邮箱)
}
EcTopologyType 枚举
public enum EcTopologyType {
NO_LINK(0), // 无链接
END_POINT(1), // 端点
LINE(2), // 中间节点(线性拓扑)
FORK(3), // 分支点
CROSS(4); // 交叉点
}
MailboxType 枚举
public enum MailboxType {
ERROR_MAILBOX(0x00), // 错误邮箱
ADS_OVER_ETHERCAT(0x01), // AoE
ETHERNET_OVER_ETHERCAT(0x02), // EoE
CANOPEN_OVER_ETHERCAT(0x03), // CoE
FILE_OVER_ETHERCAT(0x04), // FoE
SERVO_OVER_ETHERCAT(0x05), // SoE
VENDOR_OVER_ETHERCAT(0x0F); // VoE
}
子对象访问
| 方法 | 返回类型 | 说明 |
|---|---|---|
| CoE() | CoE | CANopen over EtherCAT |
| SoE() | SoE | Servo over EtherCAT |
| FoE() | FoE | File over EtherCAT |
| EoE() | EoE | Ethernet over EtherCAT |
| AoE() | AoE | ADS over EtherCAT |
| VoE() | VoE | Vendor over EtherCAT |
| FSoE() | FSoE | 功能安全 |
| CiA402() | CiA402 | CiA 402 驱动器 |
| CiA401() | CiA401 | CiA 401 I/O 模块 |
| DC() | DC | DC 同步配置 |
| PDO() | PDO | PDO 数据访问 |
| SlavePdo() | SlavePdo | 类型化 PDO 读写 |
| Diagnostics() | SlaveStats | 从站诊断统计 |
| Topology() | SlaveTopology | 从站拓扑信息 |
| MDP() | MDP | 模块化设备 |
| Esi() | Esi | ESI 信息 |
| StartupParameters() | StartupParameterList | 启动参数列表 |
所有子对象采用延迟创建模式,首次访问时自动实例化。
FMMU 属性
| 属性 | 类型 | 说明 |
|---|---|---|
| FMMU0Function() | byte | FMMU0 功能类型 |
| FMMU1Function() | byte | FMMU1 功能类型 |
| FMMU2Function() | byte | FMMU2 功能类型 |
| FMMU3Function() | byte | FMMU3 功能类型 |
SM/FMMU 查询方法
| 方法 | 返回类型 | 说明 |
|---|---|---|
| GetWatchdogConfig() | int[] | 看门狗配置 [分频器, PDI超时, PD超时],失败返回 null |
| GetWatchdogStatus() | int[] | 看门狗状态 [过期, 计数器, 分频器, 超时],失败返回 null |
FMMU 功能类型请使用 FMMU0Function() ~ FMMU3Function() 单独获取。
操作方法
SetState(EcState targetState, int timeoutMs)
public boolean SetState(EcState targetState, int timeoutMs)
public boolean SetState(EcState targetState)
设置单个从站的 EtherCAT 状态,阻塞至转换完成或超时。无 timeoutMs 重载使用默认 3000ms。
参数:
targetState(EcState) — 目标状态(INIT / PRE_OP / SAFE_OP / OP)timeoutMs(int) — 超时时间(毫秒)
返回值:
boolean— true 切换成功,false 失败或超时
示例:
Slave slave = master.getSlave(1);
if (!slave.SetState(EcState.PRE_OP)) {
System.out.println("从站 1 切换 PRE_OP 失败");
}
slave.SetState(EcState.OP, 5000);
SetWatchdog(int timeoutMs)
public boolean SetWatchdog(int timeoutMs)
设置过程数据看门狗超时(毫秒),0=禁用。
SetPdiWatchdog(int timeoutMs)
public boolean SetPdiWatchdog(int timeoutMs)
设置 PDI 看门狗超时(毫秒),0=禁用。
ConfigureDC(int sync0CycleNs, int sync1CycleNs, int shiftNs)
public void ConfigureDC(int sync0CycleNs, int sync1CycleNs, int shiftNs)
public void DisableDC()
配置/禁用 DC 同步。
PDO 数据访问请见 PDO IO。
寄存器读写
// 读取寄存器 (FPRD)
byte[] data = slave.readRegister(0x0130, 2); // 读寄存器
// 写入寄存器 (FPWR)
boolean ok = slave.writeRegister(0x0130, new byte[]{0x01, 0x00}); // 写寄存器
| 方法 | 返回类型 | 说明 |
|---|---|---|
| readRegister(int offset, int size) | byte[] | 读取从站寄存器,失败返回 null |
| writeRegister(int offset, byte[] data) | boolean | 写入从站寄存器 |
SyncManager / FMMU 配置
// 配置 SyncManager: SM编号, 起始地址, 长度, 控制字节, 启用
slave.configureSyncManager(2, 0x1100, 128, 0x24, true); // SM2 输出
// 配置 FMMU: FMMU编号, 逻辑地址, 长度, 逻辑起始位, 逻辑结束位, 物理地址, 物理起始位, 类型, 启用
slave.configureFMMU(0, 0x00010000, 128, 0, 7, 0x1100, 0, 2, true);
// 启用/禁用输出 SyncManager
slave.enableOutputSyncManager();
slave.disableOutputSyncManager();
| 方法 | 返回类型 | 说明 |
|---|---|---|
| configureSyncManager(int smIndex, int startAddr, int length, int control, boolean enable) | boolean | 配置 SyncManager |
| configureFMMU(int fmmuIndex, int logicalAddr, int length, int logicalStartBit, int logicalEndBit, int physicalAddr, int physicalStartBit, int fmmuType, boolean enable) | boolean | 配置 FMMU |
| enableOutputSyncManager() | boolean | 启用输出 SyncManager |
| disableOutputSyncManager() | boolean | 禁用输出 SyncManager |
从站身份验证
// 获取从站身份信息
int[] identity = slave.GetSlaveIdentity(); // [VendorId, ProductCode, RevisionNo, SerialNo]
// 验证从站身份是否匹配
boolean match = slave.VerifySlaveIdentity(0x00000002, 0x03F03052, 0, 0, true, false);
| 方法 | 返回类型 | 说明 |
|---|---|---|
| GetSlaveIdentity() | int[] | 获取身份信息 [VendorId, ProductCode, RevisionNo, SerialNo],失败返回 null |
| VerifySlaveIdentity(int vendorId, int productCode, int revisionNo, int serialNo, boolean checkRev, boolean checkSerial) | boolean | 验证身份是否匹配 |
ESM 超时配置
// 获取当前 ESM 状态转换超时配置
int[] timeouts = slave.GetEsmTimeouts(); // [IP, PS, SO, OS, SP, PI, BI, IB] (ms)
// 设置 ESM 状态转换超时
slave.SetEsmTimeouts(3000, 10000, 5000, 5000, 3000, 3000, 3000, 3000);
| 方法 | 返回类型 | 说明 |
|---|---|---|
| GetEsmTimeouts() | int[] | 获取 ESM 超时 [IP, PS, SO, OS, SP, PI, BI, IB] (毫秒),失败返回 null |
| SetEsmTimeouts(int ip, int ps, int so, int os, int sp, int pi, int bi, int ib) | boolean | 设置 ESM 超时 |
热插拔 / 标志
// 热插拔重配置标志
boolean needsReconfig = slave.GetNeedsStartupReconfig();
slave.ClearNeedsStartupReconfig();
// OpOnly 标志 (仅在 OP 状态下交换数据)
boolean opOnly = slave.GetOpOnlyFlag();
// 错误确认 (清除 AL 错误)
slave.SetErrorAck(true);
// 设备仿真标志
boolean emulation = slave.GetDeviceEmulationFlag();
| 方法 | 返回类型 | 说明 |
|---|---|---|
| GetNeedsStartupReconfig() | boolean | 是否需要启动重配置(热插拔后) |
| ClearNeedsStartupReconfig() | void | 清除启动重配置标志 |
| GetOpOnlyFlag() | boolean | 获取 OpOnly 标志 |
| SetErrorAck(boolean setAck) | boolean | 设置错误确认(清除 AL 错误) |
| GetDeviceEmulationFlag() | boolean | 获取设备仿真标志 |
输出数据写入
// 写入输出数据
slave.writeOutput(new byte[]{0x0F, 0x00});
// 写入单字节
slave.writeOutputByte(0, (byte) 0x0F);
| 方法 | 返回类型 | 说明 |
|---|---|---|
| writeOutput(byte[] data) | void | 写入从站输出数据 |
| writeOutputByte(int offset, byte value) | void | 写入从站输出单字节 |
ESI 自动配置
// SM/FMMU/PDO 映射
boolean ok1 = slave.configureFromEsi();
// 综合配置 (SM + DC)
boolean ok2 = slave.ConfigByEsi();
| 方法 | 返回类型 | 说明 |
|---|---|---|
| configureFromEsi() | boolean | 从 ESI 文件自动配置 SM/FMMU/PDO 映射 |
| ConfigByEsi() | boolean | 综合配置 (AutoConfigureSM + DC 配置) |
ESC 寄存器访问 (高级)
直接读写从站 ESC (EtherCAT Slave Controller) 寄存器,用于故障诊断、自定义 ESC 操作、底层调试。协议层走 FPRD/FPWR 数据报,自动 primary → secondary → APWR 三级回退。
正常使用 SDK 时无需调用 — 状态切换 / PDO / 邮箱等流程 SDK 已自动配置寄存器。此 API 用于深度诊断和特殊场景(例如读取错误计数器、强制端口策略、调试 ESI 烧写不生效等)。
寄存器定义见 ETG.1000.4 §6 / ETG.1000.6 §5(公开标准),例如:
| 寄存器 | 说明 |
|---|---|
| 0x0000 | Type / Revision / Build(设备类型) |
| 0x0030 | AL Control(主站发起状态请求) |
| 0x0130 | AL Status(从站当前状态) |
| 0x0134 | AL Status Code(错误码) |
| 0x0300-0x030F | 端口 0-3 错误计数器 |
| 0x0400-0x043F | 看门狗配置 / 计数 |
readRegister(int offset, int size)
public byte[] readRegister(int offset, int size)
读取从站 ESC 寄存器(FPRD)。
参数:
offset(int) — 寄存器地址(例如0x0130= AL Status)size(int) — 读取字节数(1 / 2 / 4 等)
返回值:
byte[]— 读取成功返回字节数组;失败(从站离线 / 超时)返回null
writeRegister(int offset, byte[] data)
public boolean writeRegister(int offset, byte[] data)
写入从站 ESC 寄存器(FPWR)。
参数:
offset(int) — 寄存器地址data(byte[]) — 写入数据
返回值:
boolean— 成功返回true
示例:
Slave slave = master.getSlave(1);
// 读取 AL Status (0x0130, 2 字节)
byte[] alStatus = slave.readRegister(0x0130, 2);
if (alStatus != null) {
int state = (alStatus[0] & 0xFF) | ((alStatus[1] & 0xFF) << 8);
System.out.printf("AL Status = 0x%04X (state=%d, err=%b)%n",
state, state & 0x0F, (state & 0x10) != 0);
}
// 读取 AL Status Code (0x0134, 错误码)
byte[] alCode = slave.readRegister(0x0134, 2);
if (alCode != null) {
int code = (alCode[0] & 0xFF) | ((alCode[1] & 0xFF) << 8);
System.out.printf("AL Status Code = 0x%04X%n", code);
}
// 写 AL Control = 0x04 (请求 SafeOp)
slave.writeRegister(0x0030, new byte[]{0x04, 0x00});
EEPROM (SII) 访问
读写从站 SII EEPROM (Slave Information Interface, ETG.1000.6 §6)。EEPROM 存储 VendorID / ProductCode / RevisionNo / SerialNo / SyncManager / FMMU / PDO 映射 / Strings 等设备身份与配置信息。SDK 在 config_init 阶段已自动读取,应用一般无需直接访问。
EEPROM 写入慎用 — 写错可能导致从站身份信息错乱,严重时永久 brick 从站, 需厂家工具恢复。仅在以下场景使用:
- 烧写 alias 地址(Hot-Connect 别名)
- 修复出厂数据被误覆盖
- 厂商授权的固件 / 参数烧录
EEPROM 写需要从站处于 Init / PreOp 状态,OP 状态下写入会被拒绝。
EEPROM 大小通常 1 KB - 16 KB(按 word 寻址,1 word = 2 byte)。起始 8 word 为厂商基本信息,之后是 Category 链表(Strings / General / FMMU / SyncM / TxPdo / RxPdo / DC / End=0xFFFF)。
readEeprom(int byteOffset, int byteLength)
public byte[] readEeprom(int byteOffset, int byteLength)
读取从站 SII EEPROM 字节区域。SDK 自动处理 BUSY 轮询、字对齐。
参数:
byteOffset(int) — 起始字节偏移 (建议偶数对齐)byteLength(int) — 读取字节数 (建议偶数)
返回值:
byte[]—byteLength字节数据; 参数非法返回null, 读失败返回null
writeEeprom(int byteOffset, byte[] data)
public boolean writeEeprom(int byteOffset, byte[] data)
写入从站 SII EEPROM 字节区域。byteOffset 与 data.length 都必须是偶数。
参数:
byteOffset(int) — 起始字节偏移 (必须偶数)data(byte[]) — 写入字节 (长度必须偶数)
返回值:
boolean— 全部 word 成功写入返回true
示例:
Slave slave = master.getSlave(1);
// 读 vendor_id (EEPROM 字节偏移 0x10, 长度 4)
byte[] data = slave.readEeprom(0x10, 4);
if (data != null && data.length == 4) {
int vendorId = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8)
| ((data[2] & 0xFF) << 16) | ((data[3] & 0xFF) << 24);
System.out.printf("VendorID = 0x%08X%n", vendorId);
}
// 读取头部 16 字节 (含 PDIControl/StationAlias 等)
byte[] header = slave.readEeprom(0, 16);
// 写 alias address (EEPROM 字节偏移 0x08)
// 必须从站处于 Init/PreOp 状态!
if (slave.State() == EcState.Init) {
slave.writeEeprom(0x08, new byte[]{0x01, 0x00}); // alias = 1
}
- 首选:
readEeprom / writeEeprom(按字节, 自动字对齐) - 次选:
slave.VendorId() / ProductId() / SerialNumber()等已封装属性
DL Port 端口控制
直接读写 ESC 的 DL Port Control 寄存器 (0x0101),用于端口故障注入测试和冗余/环拓扑的手动诊断。
正常运行时无需调用。大部分用户应该通过订阅 addSlavePortLinkChangedListener 事件和读取 端口错误计数器 来诊断端口状态。仅在需要主动模拟端口故障(测试冗余切换)或排查特定端口问题时使用。
ESC 有 4 个物理端口 P0 / P1 / P2 / P3,DL Port Control 寄存器的位定义如下:
| DLPORT 值 | 行为 |
|---|---|
| 0x00 | Auto — 所有端口由 ESC 自动管理(默认) |
| 0x03 | 关闭 P0 |
| 0x0C | 关闭 P1 |
| 0x30 | 关闭 P2 |
| 0xC0 | 关闭 P3 |
SDK 自动采用 primary → secondary → APWR 三级回退写入路径,即使 P0 关闭后仍能通过副网口/广播恢复。
WriteDLPort(byte value)
public boolean WriteDLPort(byte value)
写入从站 DL Port 控制寄存器(0x0101)。
参数:
value(byte) — DLPORT 值(见上表)
返回值:
boolean— 成功返回true
ReadDLPort()
public byte ReadDLPort()
读取从站 DL Port 控制寄存器的当前值。
返回值:
byte— 当前 DLPORT 值;读取失败返回0
示例:
// 模拟 P1 端口故障 (测试冗余切换)
boolean ok = slave.WriteDLPort((byte) 0x0C);
System.out.println("关闭 P1: " + (ok ? "成功" : "失败"));
// 读回确认
byte dlport = slave.ReadDLPort();
System.out.printf("当前 DLPORT = 0x%02X%n", dlport);
// 故障恢复后还原
slave.WriteDLPort((byte) 0x00); // 恢复 Auto
关闭一个端口后,观察 addSlavePortLinkChangedListener 和 master.Diagnostics().getAllBreakPoints() 验证冗余切换是否生效。
完整示例
Slave slave = master.getSlave(1);
// 基本信息
System.out.println("名称: " + slave.Name());
System.out.println("厂商: 0x" + Integer.toHexString(slave.VendorId()));
System.out.println("状态: " + slave.State());
// 子对象
CoE coe = slave.CoE();
CiA402 drv = slave.CiA402();
PDO pdo = slave.PDO();
// 可读写属性
slave.Group((byte) 1); // 分配到组 1
slave.IsOptional(true); // 标记为可选从站