跳到主要内容

Slave 属性与方法

通过 master.getSlave(n) 访问(1-based 索引)或 master.Slaves() 获取列表。

提示
  • PDO 输入输出(指针访问、字节数组、类型化访问等)请参见 PDO 输入输出 页面。
  • 从站事件请参见 事件 页面。
  • 从站诊断请参见 从站诊断 页面。

属性

类别属性类型读写说明
基本标识SlaveNumshort (public final)只读从站编号(1-based,不变值)
MasterIndexshort (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 读取)
HasMDP()boolean只读是否支持模块化设备配置文件(ETG.5001)
BlockLRW()boolean只读逻辑读写操作阻止标志
地址ConfigAddr()short只读物理配置地址
AliasAddress()short只读别名地址
Index()int只读从站索引(SlaveNum 别名)
状态State()EcState只读从站当前 EtherCAT 状态(走内核缓存,OP 期由 PDO 线程刷新)
StateLive()EcState只读当前状态(强制刷一帧实时读,绕过缓存;用于掉 OP 检测/调试,旧 DLL 降级 UNKNOWN)
ErrorCode()EcALState只读AL Status Code 错误码
ErrorCodeLive()EcALState只读AL Status Code(强制实时读,绕过缓存)
IsLost()boolean只读从站是否丢失(断开连接)
WcContributed()EcWcContributed只读本周期对工作计数器(WKC)的贡献状态(零帧实时镜像),详见 WKC 贡献语义
AlStatusMirror()EcAlStatusMirror只读AL 状态镜像(零帧实时,含 AL State + Error + Code)
拓扑TopologyByte()byte只读拓扑类型 (0=无链接, 1=端点, 2=中间, 3=分支, 4=交叉)
ParentStation()int只读父从站的站地址 (注: 实际是从站索引 1-based, 不是 station address; 0 表示父节点是主站)
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 版本号
EEPROMEep8ByteAddressing()boolean只读EEPROM 寻址模式(true=8字节, false=4字节)
EepPDI()byte只读物理设备接口(PDI)类型
EbusCurrent()short只读E-bus 电流消耗(mA)
邮箱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)
FMMUFMMU0Function()byte只读FMMU0 功能类型(bit 0=输出, bit 1=输入)
FMMU1Function()byte只读FMMU1 功能类型
FMMU2Function()byte只读FMMU2 功能类型
FMMU3Function()byte只读FMMU3 功能类型
DCHasDC()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 前设置)

EcWcContributed 枚举

WcContributed() 返回此枚举,反映该从站本周期是否对工作计数器(WKC)有贡献。详见 WKC 贡献语义

public enum EcWcContributed {
CONTRIBUTED(1), // 该从站本周期正常贡献 WKC(在线响应)
NOT_CONTRIBUTED(0), // 该从站本周期未贡献(疑似掉站 / 热插拔中)
UNKNOWN(0xFF); // 契约未就绪 — 诚实暴露,绝不臆造 1/0

public boolean isKnown(); // 是否数据可信(非 UNKNOWN)
}

EcAlStatusMirror 解析对象

AlStatusMirror() 返回此对象(零帧实时镜像),含 AL State + Error 位 + AL Status Code。raw == 0isKnown() 为 false(内核尚无该从站镜像)。

public static final class EcAlStatusMirror {
public static EcAlStatusMirror fromRaw(int rawUnsigned);
public EcState alState(); // AL State(低字节,丢 Error 位取低 4 位)
public boolean hasError(); // Error 位(bit4)
public EtherCATTypes.EcALState alStatusCode(); // AL Status Code(高字节)
public boolean isKnown(); // raw != 0 时为 true
}

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()CoECANopen over EtherCAT
SoE()SoEServo over EtherCAT
FoE()FoEFile over EtherCAT
EoE()EoEEthernet over EtherCAT
AoE()AoEADS over EtherCAT
VoE()VoEVendor over EtherCAT
FSoE()FSoE功能安全
CiA402()CiA402CiA 402 驱动器
CiA401()CiA401CiA 401 I/O 模块
DC()DCDC 同步配置
PDO()PDOPDO 数据访问
SlavePdo()SlavePdo类型化 PDO 读写
Diagnostics()SlaveStats从站诊断统计
Topology()SlaveTopology从站拓扑信息
MDP()MDP模块化设备
Esi()EsiESI 信息
StartupParameters()StartupParameterList启动参数列表
延迟创建

所有子对象采用延迟创建模式,首次访问时自动实例化。

Java 特有语法糖

Java 可用 Optional<Slave> 链式访问子对象/拓扑信息 (MasterStreams.slaveOpt(master, idx).map(Slave::Topology)...), 越界 / 已 dispose / 未 build 时安全返回空, 不抛 IndexOutOfBoundsException. 详见 Optional<Slave>Stream API.

FMMU 属性

属性类型说明
FMMU0Function()byteFMMU0 功能类型
FMMU1Function()byteFMMU1 功能类型
FMMU2Function()byteFMMU2 功能类型
FMMU3Function()byteFMMU3 功能类型

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

实时诊断镜像 (薄读零帧)

WcContributed() / AlStatusMirror() 是内核 per-slave 诊断缓存的薄读:每次调用直接读 native,不收发帧(零帧),不二次缓存,读到即此刻总线现实,无需手动刷新。旧 DLL 未导出该 getter 时降级为 UNKNOWN / raw=0,诚实不臆造。

WKC 贡献语义

WcContributed() 反映此刻该从站是否真的在响应

  • CONTRIBUTED — 该从站正常贡献工作计数器(WKC),即聚合 WKC 完整(actual == expected,亦即缺口 WcDeficit == 0)时各从站逐字节比对都"满"。
  • NOT_CONTRIBUTED — 该从站此刻没在贡献 WKC(疑似掉站 / 热插拔恢复中)。这不是 master 故障,从站修复后内核镜像自然回到 CONTRIBUTED
  • UNKNOWN — 契约未就绪(内核尚无该从站镜像),诚实暴露,不臆造为"已贡献"。
R1 可靠性铁律

本方法仅"如实反映总线现实", 不参与任何 WKC 篡改 / 迁就逻辑。逐从站贡献位是聚合 WKC 缺口(expected - actual)的逐站分解:缺口大于 0 表示有从站此刻未贡献,应报警 + 诊断,不下调 expected、不停 OP

示例:

for (Slave slave : master.Slaves()) {
if (slave.WcContributed() == EcatSlaveDiag.EcWcContributed.NOT_CONTRIBUTED) {
EcatSlaveDiag.EcAlStatusMirror al = slave.AlStatusMirror();
System.out.printf("从站 %d 此刻未贡献 WKC(疑似掉站),%s%n", slave.SlaveNum, al);
}
}

寄存器读写

// 读取寄存器 (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验证身份是否匹配
Java 特有语法糖

Java 可用 SlaveIdentity record-like 不可变身份对象抓快照 — 跨线程传递安全、可作 HashMap key、易序列化, Java 14+ 升级到真 record 调用代码无需改动. 详见 record (Java 14+) 等价物.

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();
方法返回类型说明
SetEsiFile(String filePath)int为该从站设置 ESI 文件路径(0=成功,负数=错误)
configureFromEsi()boolean从 ESI 文件自动配置 SM/FMMU/PDO 映射
ConfigByEsi()boolean综合配置 (AutoConfigureSM + DC 配置)

ESC 寄存器访问 (高级)

直接读写从站 ESC (EtherCAT Slave Controller) 寄存器,用于故障诊断自定义 ESC 操作底层调试。协议层走 FPRD/FPWR 数据报,自动 primary → secondary → APWR 三级回退。

高级 API

正常使用 SDK 时无需调用 — 状态切换 / PDO / 邮箱等流程 SDK 已自动配置寄存器。此 API 用于深度诊断特殊场景(例如读取错误计数器、强制端口策略、调试 ESI 烧写不生效等)。

寄存器定义见 ETG.1000.4 §6 / ETG.1000.6 §5(公开标准),例如:

寄存器说明
0x0000Type / Revision / Build(设备类型)
0x0030AL Control(主站发起状态请求)
0x0130AL Status(从站当前状态)
0x0134AL 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 字节区域。byteOffsetdata.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) 用于端口故障注入测试冗余/环拓扑的手动诊断。Java SDK 提供专用的 writeDLPort / readDLPort 方法直接访问 0x0101(也可用通用的 writeRegister / readRegister)。

writeDLPort(byte value) / readDLPort()

public boolean writeDLPort(byte value)
public byte readDLPort()
  • writeDLPort(value) — 写入 DL Port Control 寄存器(0x0101),成功返回 true
  • readDLPort() — 读取当前 DLPORT 值,读失败返回 0

参数:

  • value (byte) — DLPORT 值(0x00=Auto, 0x03=P0 关, 0x0C=P1 关, 0x30=P2 关, 0xC0=P3 关)
高级 API

正常运行时无需调用。大部分用户应该通过订阅 addSlavePortLinkChangedListener 事件和读取 端口错误计数器 来诊断端口状态。仅在需要主动模拟端口故障(测试冗余切换)或排查特定端口问题时使用。

ESC 有 4 个物理端口 P0 / P1 / P2 / P3DL Port Control 寄存器的位定义如下:

DLPORT 值行为
0x00Auto — 所有端口由 ESC 自动管理(默认)
0x03关闭 P0
0x0C关闭 P1
0x30关闭 P2
0xC0关闭 P3

writeRegister / readRegister 内部采用 primary → secondary → APWR 三级回退写入路径,即使 P0 关闭后仍能通过副网口/广播恢复。

示例:

// 模拟 P1 端口故障 (测试冗余切换) — 专用方法
boolean ok = slave.writeDLPort((byte) 0x0C);
System.out.println("关闭 P1: " + (ok ? "成功" : "失败"));

// 读回确认
byte dlport = slave.readDLPort();
System.out.printf("当前 DLPORT = 0x%02X%n", dlport & 0xFF);

// 故障恢复后还原
slave.writeDLPort((byte) 0x00); // 恢复 Auto
配合冗余诊断

关闭一个端口后,观察 addSlavePortLinkChangedListenermaster.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); // 标记为可选从站