跳到主要内容

主站对象字典 (Master OD)

符合 ETG.1510 标准的主站对象字典,提供主站身份信息、从站配置/状态/诊断数据,供外部诊断工具和 HMI 通过标准 SDO 接口访问。

通过 master.MasterOD() 访问。

ETG.1510 标准

主站对象字典按照 ETG.1510 规范实现,使用标准 CoE 索引约定。与从站 CoE 对象字典不同,这里是主站自身暴露的诊断对象。配合邮箱网关使用,可实现远程诊断工具对主站的标准访问。

对象索引总览

索引名称子索引数读写说明
0x1000Device Type0只读0x00001389(EtherCAT Master)
0x1008Device Name0只读"Darra EtherCAT Master"
0x1009Hardware Version0只读x64
0x100ASoftware Version0只读SDK 版本号
0x1018Identity Object4只读主站身份信息(见下方子索引表)
0x8nnnConfiguration Data40只读第 n 个从站的配置数据(地址、名称、厂商、邮箱等)
0x9nnnInformation Data32只读第 n 个从站的检测信息(实际地址、厂商 ID、DL Status)
0xAnnnDiagnosis Data19部分可写第 n 个从站的诊断数据(AL Status、错误计数、链路等)
0xF002Detect Modules3只读从站扫描状态(禁止外部写入)
0xF120Master Diag Data16只读主站诊断数据(丢帧率、帧频、状态)
0xF200Diag Interface Control16可写诊断接口控制(复位诊断信息)
备注

nnn = 从站编号(1-based),索引根据 master.SlaveCount() 动态生成。例如 3 个从站时,0x8001 ~ 0x80030x9001 ~ 0x90030xA001 ~ 0xA003 均可访问。

0x1018 — 主站身份 (Identity Object)

子索引名称类型说明
0Number of Entriesbyte4固定
1Vendor IDint0x00001164ETG 分配,固定值
2Product Codeint0x00000001固定值
3Revision Numberint自动自动从 DLL 版本派生(高字=主版本,低字=次版本)
4Serial Numberint自动自增每个实例自动分配 0, 1, 2...,用于多主站实例区分

0x8nnn — 从站配置数据

每个从站对应一个 0x8nnn 对象(nnn = 从站编号),包含 ENI 中配置的静态信息。

子索引名称类型读写说明
0Number of Entriesbyte只读固定 40
1Fixed Station Addressshort只读配置地址(ConfigAddr)
2TypeString只读设备类型字符串(DriveName)
3NameString只读设备名称
4Device Typeint只读设备类型编码
5Vendor IDint只读厂商 ID
6Product Codeint只读产品代码
7Revision Numberint只读修订号
8Serial Numberint只读序列号
33Mailbox Out Sizeshort只读SM0 邮箱输出大小
34Mailbox In Sizeshort只读SM1 邮箱输入大小
35Link Statusbyte只读端口链路状态(低4位:端口连接,高4位:物理链路)
36Link Presetbyte只读端口链路预设(根据拓扑设置)
37Flagsbyte只读从站标志(Bit3: 热连接组成员)
38Port Physicsshort只读端口物理类型
39Mailbox Protocolsshort只读支持的邮箱协议(CoE=0x04, FoE=0x08 等)
40Diag History Supportedbyte只读是否支持 0x10F3 诊断历史对象

0x9nnn — 从站检测信息

每个从站对应一个 0x9nnn 对象,包含运行时检测到的实际信息。

子索引名称类型读写说明
0Number of Entriesbyte只读固定 32
1Station Addressshort只读实际配置地址
5Vendor IDint只读检测到的厂商 ID
6Product Codeint只读检测到的产品代码
7Revision Numberint只读检测到的修订号
8Serial Numberint只读检测到的序列号
32DL Statusshort只读DL Status 寄存器(ESC 0x0110-0x0111)

0xAnnn — 从站诊断数据

每个从站对应一个 0xAnnn 对象,包含实时诊断数据。每次读取时自动更新。

子索引名称类型读写说明
0Number of Entriesbyte只读固定 19
1AL Statusshort只读当前 AL 状态
2AL Controlshort可写写入时同步到从站
3Last AL Status Codeshort只读最近一次 AL 错误码(ESC 0x0134)
4Link Conn. Statusbyte只读端口链路连接状态
5Link Controlbyte只读链路控制(DL Control 寄存器 0x0101)
6Fixed Addr Conn. Port 0short只读Port 0 连接的从站配置地址
7Fixed Addr Conn. Port 1short只读Port 1 连接的从站配置地址
8Fixed Addr Conn. Port 2short只读Port 2 连接的从站配置地址
9Fixed Addr Conn. Port 3short只读Port 3 连接的从站配置地址
10Frame Error Port 0int只读Port 0 帧错误计数
11Frame Error Port 1int只读Port 1 帧错误计数
12Frame Error Port 2int只读Port 2 帧错误计数
13Frame Error Port 3int只读Port 3 帧错误计数
14Cyclic WC Error Counterint只读周期性工作计数器错误
15Slave Not Present Counterint只读从站不在线计数
16Abnormal State Change Counterint只读异常状态变化计数
17Disable Auto Link Controlbyte只读自动链路控制禁用标志
18Last CoE/SoE Protocol Errorint只读最近一次 CoE/SoE 协议错误码
19New Diag Messagesbyte只读是否有新诊断消息(通过 0x10F3 检测)

0xF002 — 扫描命令

安全保护

0xF002 扫描命令禁止外部写入。运行中执行扫描可能导致配置丢失和设备异常,因此该对象为只读。 从站扫描仅在主站初始化阶段由内部逻辑执行。 更多功能请等待未来更新。

子索引名称类型读写说明
0Number of Entriesbyte只读固定 3
1Scan Command Requestshort只读扫描命令请求(禁止外部写入)
2Scan Command Statusbyte只读1=完成无错误, 3=完成有错误, 255=执行中
3Scan Command Responsebyte[6]只读状态 + 错误码 + 检测到的从站数

0xF120 — 主站诊断数据

子索引名称类型读写说明
0Number of Entriesbyte只读固定 16
1Cyclic Lost Framesint只读周期性丢帧率(百分比 x 100)
2Acyclic Lost Framesint只读非周期性丢帧率(当前返回 0)
3Cyclic Frames/Secondint只读每秒周期帧数
4Acyclic Frames/Secondint只读每秒非周期帧数(当前返回 0)
16Master Stateshort只读主站当前 EtherCAT 状态

0xF200 — 诊断接口控制

子索引名称类型读写说明
0Number of Entriesbyte只读固定 16
16Reset Diag Infobyte可写写入 1 复位所有从站和主站的诊断计数器(上升沿触发)

方法

readObject(int index, byte subindex)

public byte[] readObject(int index, byte subindex)

读取主站对象字典中指定索引的数据。

参数:

  • index (int) — 对象索引(如 0x10180x80010xA001
  • subindex (byte) — 子索引

返回值:

  • byte[] — 读取的原始数据,未知对象返回 null

示例:

byte[] vid = master.MasterOD().readObject(0x8001, (byte) 5);
int vendorId = ByteBuffer.wrap(vid).order(ByteOrder.LITTLE_ENDIAN).getInt();

writeObject(int index, byte subindex, byte[] data)

public boolean writeObject(int index, byte subindex, byte[] data)

写入主站对象字典。仅部分对象支持写入(见上方各对象表格的读写列)。

参数:

  • index (int) — 对象索引
  • subindex (byte) — 子索引
  • data (byte[]) — 要写入的数据

返回值:

  • boolean — 写入成功返回 true

getObjectName(int index)

public String getObjectName(int index)

获取对象的名称。

参数:

  • index (int) — 对象索引

返回值:

  • String — 对象名称,未知索引返回 null

getSubindexCount(int index)

public byte getSubindexCount(int index)

获取对象的子索引数量。

参数:

  • index (int) — 对象索引

返回值:

  • byte — 子索引数量

getSupportedObjectIndices()

public List<Integer> getSupportedObjectIndices()

获取当前支持的所有对象索引列表(固定索引 + 按从站数量动态生成的 0x8nnn/0x9nnn/0xAnnn)。

返回值:

  • List<Integer> — 支持的索引列表

快捷方法

MasterObjectDictionary 同时提供 ETG.1510 常用诊断字段的便捷读取接口(内部等同于读 0xAnnn 的对应子索引):

int  alExt    = od.ALStatusExtended(1);          // 扩展 AL 状态码
int alLast = od.LastALStatusCode(1); // 最近 AL 错误码
long protoErr = od.LastCoESoEProtocolError(1); // 最近 CoE/SoE 协议错误码
long wkcErr = od.CyclicWCErrorCounter(1); // WKC 错误计数
boolean hasNew = od.NewDiagMessagesAvailable(1); // 是否有新诊断消息
boolean autoOff = od.DisableAutomaticLinkControl(1); // 自动链路控制禁用标志

完整示例

MasterObjectDictionary od = master.MasterOD();

// 遍历所有从站的诊断数据
for (int i = 1; i <= master.SlaveCount(); i++) {
int cfgIdx = 0x8000 | i;
int diagIdx = 0xA000 | i;

// 读取从站名称
byte[] nameData = od.readObject(cfgIdx, (byte) 3);
String name = nameData != null ? new String(nameData, java.nio.charset.StandardCharsets.US_ASCII) : "N/A";

// 读取 AL Status 和错误码
byte[] alStatus = od.readObject(diagIdx, (byte) 1);
byte[] alCode = od.readObject(diagIdx, (byte) 3);

// 读取各端口帧错误计数
int[] portErrors = new int[4];
for (byte p = 0; p < 4; p++) {
byte[] err = od.readObject(diagIdx, (byte) (10 + p));
if (err != null && err.length >= 4) {
portErrors[p] = ByteBuffer.wrap(err).order(ByteOrder.LITTLE_ENDIAN).getInt();
}
}

int alVal = (alStatus != null && alStatus.length >= 2)
? ByteBuffer.wrap(alStatus).order(ByteOrder.LITTLE_ENDIAN).getShort() & 0xFFFF : 0;
int codeVal = (alCode != null && alCode.length >= 2)
? ByteBuffer.wrap(alCode).order(ByteOrder.LITTLE_ENDIAN).getShort() & 0xFFFF : 0;

System.out.printf("从站%d [%s]: AL=0x%04X, Code=0x%04X, Errors=[%d,%d,%d,%d]%n",
i, name, alVal, codeVal,
portErrors[0], portErrors[1], portErrors[2], portErrors[3]);
}

// 复位所有诊断
od.writeObject(0xF200, (byte) 16, new byte[] { 1 });

// 列出所有支持的对象
List<Integer> indices = od.getSupportedObjectIndices();
for (int idx : indices) {
String name = od.getObjectName(idx);
System.out.printf("0x%04X: %s%n", idx, name);
}

// ETG.1510 诊断快捷方法
int alStatus = od.ALStatusExtended(1);
long wkcErrors = od.CyclicWCErrorCounter(1);
boolean hasNewDiag = od.NewDiagMessagesAvailable(1);