主站对象字典 (Master OD)
符合 ETG.1510 标准的主站对象字典,提供主站身份信息、从站配置/状态/诊断数据,供外部诊断工具和 HMI 通过标准 SDO 接口访问。
通过 master.MasterOD 访问。
ETG.1510 标准
主站对象字典按照 ETG.1510 规范实现,使用标准 CoE 索引约定。与从站 CoE 对象字典不同,这里是主站自身暴露的诊断对象。配合邮箱网关使用,可实现远程诊断工具对主站的标准访问。
对象索引总览
| 索引 | 名称 | 子索引数 | 读写 | 说明 |
|---|---|---|---|---|
| 0x1000 | Device Type | 0 | 只读 | 0x00001389(EtherCAT Master) |
| 0x1008 | Device Name | 0 | 只读 | "Darra EtherCAT Master" |
| 0x1009 | Hardware Version | 0 | 只读 | 进程位数:64 位进程返回 "x64",32 位进程返回 "x86" |
| 0x100A | Software Version | 0 | 只读 | DLL 版本号字符串 |
| 0x1018 | Identity Object | 4 | 只读 | 主站身份信息(见下方子索引表) |
| 0x8nnn | Configuration Data | 40 | 只读 | 第 n 个从站的配置数据(地址、名称、厂商、邮箱等) |
| 0x9nnn | Information Data | 32 | 只读 | 第 n 个从站的检测信息(实际地址、厂商 ID、DL Status) |
| 0xAnnn | Diagnosis Data | 19 | 部分可写 | 第 n 个从站的诊断数据(AL Status、错误计数、链路等) |
| 0xF002 | Detect Modules | 3 | 只读 | 从站扫描状态(禁止外部写入) |
| 0xF120 | Master Diag Data | 16 | 只读 | 主站诊断数据(丢帧计数、帧频、状态) |
| 0xF200 | Diag Interface Control | 16 | 可写 | 诊断接口控制(复位诊断信息) |
备注
nnn = 从站编号(1-based),索引根据 master.SlaveCount 动态生成。例如 3 个从站时,0x8001 ~ 0x8003、0x9001 ~ 0x9003、0xA001 ~ 0xA003 均可访问。
0x1018 — 主站身份 (Identity Object)
| 子索引 | 名称 | 类型 | 值 | 说明 |
|---|---|---|---|---|
| 0 | Number of Entries | byte | 4 | 固定 |
| 1 | Vendor ID | uint | 0x00001164 | ETG 分配,固定值 |
| 2 | Product Code | uint | 0x00000001 | 固定值 |
| 3 | Revision Number | uint | 自动 | 自动从 DLL 版本派生(高字=主版本,低字=次版本) |
| 4 | Serial Number | uint | 自动自增 | 每个实例自动分配 0, 1, 2…,用于多主站实例区分 |
0x8nnn — 从站配置数据
每个从站对应一个 0x8nnn 对象(nnn = 从站编号),包含 ENI 中配置的静态信息。
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0 | Number of Entries | byte | 只读 | 固定 40 |
| 1 | Fixed Station Address | ushort | 只读 | 配置地址(ConfigAddr) |
| 2 | Type | string | 只读 | 设备类型字符串(DriveName) |
| 3 | Name | string | 只读 | 设备名称 |
| 4 | Device Type | uint | 只读 | 设备类型编码(当前恒 0,Dtype 已无真值源) |
| 5 | Vendor ID | uint | 只读 | 厂商 ID |
| 6 | Product Code | uint | 只读 | 产品代码 |
| 7 | Revision Number | uint | 只读 | 修订号 |
| 8 | Serial Number | uint | 只读 | 序列号 |
| 33 | Mailbox Out Size | ushort | 只读 | SM0 邮箱输出大小 |
| 34 | Mailbox In Size | ushort | 只读 | SM1 邮箱输入大小 |
| 35 | Link Status | byte | 只读 | 端口链路状态(Bit0=无链路;Bit4-7=端口 0-3 连接状态) |
| 36 | Link Preset | byte | 只读 | 端口链路预设(根据拓扑设置) |
| 37 | Flags | byte | 只读 | 从站标志(规范 Bit3=热连接组成员;当前恒 0,热连接组检测暂不支持) |
| 38 | Port Physics | ushort | 只读 | 端口物理类型 |
| 39 | Mailbox Protocols | ushort | 只读 | 支持的邮箱协议(CoE=0x04, FoE=0x08 等) |
| 40 | Diag History Supported | byte | 只读 | 是否支持 0x10F3 诊断历史对象(0=不支持;CoE 对象字典未加载时返回 null,诊断读路径不做总线扫描) |
0x9nnn — 从站检测信息
每个从站对应一个 0x9nnn 对象,包含运行时检测到的实际信息。
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0 | Number of Entries | byte | 只读 | 固定 32 |
| 1 | Station Address | ushort | 只读 | 实际配置地址 |
| 5 | Vendor ID | uint | 只读 | 检测到的厂商 ID |
| 6 | Product Code | uint | 只读 | 检测到的产品代码 |
| 7 | Revision Number | uint | 只读 | 检测到的修订号 |
| 8 | Serial Number | uint | 只读 | 检测到的序列号 |
| 32 | DL Status | ushort | 只读 | DL Status 寄存器(ESC 0x0110-0x0111) |
0xAnnn — 从站诊断数据
每个从站对应一个 0xAnnn 对象,包含实时诊断数据。每次读取时自动更新。
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0 | Number of Entries | byte | 只读 | 固定 19 |
| 1 | AL Status | ushort | 只读 | 当前 AL 状态 |
| 2 | AL Control | ushort | 可写 | 写入时同步到从站 |
| 3 | Last AL Status Code | ushort | 只读 | 最近一次 AL 错误码(ESC 0x0134) |
| 4 | Link Conn. Status | byte | 只读 | 端口链路连接状态 |
| 5 | Link Control | byte | 只读 | 链路控制(DL Control 寄存器 0x0101) |
| 6 | Fixed Addr Conn. Port 0 | ushort | 只读 | Port 0 连接的从站配置地址 |
| 7 | Fixed Addr Conn. Port 1 | ushort | 只读 | Port 1 连接的从站配置地址 |
| 8 | Fixed Addr Conn. Port 2 | ushort | 只读 | Port 2 连接的从站配置地址 |
| 9 | Fixed Addr Conn. Port 3 | ushort | 只读 | Port 3 连接的从站配置地址 |
| 10 | Frame Error Port 0 | uint | 只读 | Port 0 帧错误计数 |
| 11 | Frame Error Port 1 | uint | 只读 | Port 1 帧错误计数 |
| 12 | Frame Error Port 2 | uint | 只读 | Port 2 帧错误计数 |
| 13 | Frame Error Port 3 | uint | 只读 | Port 3 帧错误计数 |
| 14 | Cyclic WC Error Counter | uint | 只读 | 周期性工作计数器错误(无真值源,读取返回 null,子索引不可用) |
| 15 | Slave Not Present Counter | uint | 只读 | 从站不在线计数(无真值源,读取返回 null,子索引不可用) |
| 16 | Abnormal State Change Counter | uint | 只读 | 异常状态变化计数(无真值源,读取返回 null,子索引不可用) |
| 17 | Disable Auto Link Control | byte | 只读 | 无真值源,读取返回 null(子索引不可用),不要当成 false |
| 18 | Last CoE/SoE Protocol Error | uint | 只读 | 最近一次 CoE/SoE 协议错误码 |
| 19 | New Diag Messages | byte | 只读 | 是否有新诊断消息(仅当真读到从站 0x10F3:4 才回答;无真值源返回 null) |
0xF002 — 扫描命令
安全保护
0xF002 扫描命令禁止外部写入。运行中执行扫描可能导致配置丢失和设备异常,因此该对象为只读。
从站扫描仅在主站初始化阶段由内部逻辑执行。
更多功能请等待未来更新。
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0 | Number of Entries | byte | 只读 | 固定 3 |
| 1 | Scan Command Request | ushort | 只读 | 扫描命令请求(禁止外部写入) |
| 2 | Scan Command Status | byte | 只读 | 恒 1(扫描命令禁写,状态机不离开空闲态;规范语义 1=完成无错误, 3=完成有错误, 255=执行中) |
| 3 | Scan Command Response | byte[6] | 只读 | 状态 + 保留 0 + 错误码(2 字节)+ 当前从站数(2 字节,实时值) |
0xF120 — 主站诊断数据
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0 | Number of Entries | byte | 只读 | 固定 16 |
| 1 | Cyclic Lost Frames | uint | 只读 | 周期性丢帧计数(读内核丢帧计数器原值,不是百分比) |
| 2 | Acyclic Lost Frames | uint | 只读 | 非周期性丢帧计数(本实现固定返回 0) |
| 3 | Cyclic Frames/Second | uint | 只读 | 每秒周期帧数 |
| 4 | Acyclic Frames/Second | uint | 只读 | 每秒非周期帧数(本实现固定返回 0) |
| 16 | Master State | ushort | 只读 | 主站当前 EtherCAT 状态 |
0xF120:01 的取数口径
本腿读内核丢帧计数器 lost_frames 的原值(GetDiagnosticsPointer 零拷贝直读,自计数起点起只增;0xF200:16 复位时归零),是丢帧次数不是丢帧率百分比。
0xF200 — 诊断接口控制
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0 | Number of Entries | byte | 只读 | 固定 16 |
| 16 | Reset Diag Info | byte | 可写 | 写入 1 复位所有从站和主站的诊断计数器(上升沿触发) |
方法
ReadObject(ushort index, byte subindex)
public byte[] ReadObject(ushort index, byte subindex)
读取主站对象字典中指定索引的数据。
参数:
index(ushort) — 对象索引(如0x1018、0x8001、0xA001)subindex(byte) — 子索引
返回值:
byte[]— 读取的原始数据,未知对象返回null
示例:
byte[] vid = master.MasterOD.ReadObject(0x8001, 5);
uint vendorId = BitConverter.ToUInt32(vid, 0);
WriteObject(ushort index, byte subindex, byte[] data)
public bool WriteObject(ushort index, byte subindex, byte[] data)
写入主站对象字典。仅部分对象支持写入(见上方各对象表格的读写列)。
参数:
index(ushort) — 对象索引subindex(byte) — 子索引data(byte[]) — 要写入的数据
返回值:
bool— 写入成功返回true
GetObjectName(ushort index)
public string GetObjectName(ushort index)
获取对象的名称。
参数:
index(ushort) — 对象索引
返回值:
string— 对象名称,未知索引返回"Unknown (原始值: …)"形式的字符串
GetSubindexCount(ushort index)
public byte GetSubindexCount(ushort index)
获取对象的子索引数量。
参数:
index(ushort) — 对象索引
返回值:
byte— 子索引数量
GetSupportedObjectIndices()
public List<ushort> GetSupportedObjectIndices()
获取当前支持的所有对象索引列表(固定索引 + 按从站数量动态生成的 0x8nnn/0x9nnn/0xAnnn)。
返回值:
List<ushort>— 支持的索引列表
快捷方法
// 等同于 master.MasterOD.ReadObject(index, subindex)
byte[] data = master.ReadMasterObject(0x1018, 1);
// 等同于 master.MasterOD.WriteObject(index, subindex, data)
bool ok = master.WriteMasterObject(0xF200, 16, new byte[] { 1 });
完整示例
var od = master.MasterOD;
// 遍历所有从站的诊断数据
for (ushort i = 1; i <= master.SlaveCount; i++)
{
ushort cfgIdx = (ushort)(0x8000 | i);
ushort diagIdx = (ushort)(0xA000 | i);
// 读取从站名称
byte[] nameData = od.ReadObject(cfgIdx, 3);
string name = nameData != null ? Encoding.ASCII.GetString(nameData) : "N/A";
// 读取 AL Status 和错误码
byte[] alStatus = od.ReadObject(diagIdx, 1);
byte[] alCode = od.ReadObject(diagIdx, 3);
// 读取各端口帧错误计数
uint[] portErrors = new uint[4];
for (byte p = 0; p < 4; p++)
{
byte[] err = od.ReadObject(diagIdx, (byte)(10 + p));
if (err != null) portErrors[p] = BitConverter.ToUInt32(err, 0);
}
Console.WriteLine($"从站{i} [{name}]: " +
$"AL=0x{BitConverter.ToUInt16(alStatus ?? new byte[2], 0):X4}, " +
$"Code=0x{BitConverter.ToUInt16(alCode ?? new byte[2], 0):X4}, " +
$"Errors=[{string.Join(",", portErrors)}]");
}
// 复位所有诊断
od.WriteObject(0xF200, 16, new byte[] { 1 });