跳到主要内容

主站对象字典 (Master OD)

符合 ETG.1510 标准的主站对象字典,提供主站身份信息和诊断数据。

ETG.1510 标准

主站对象字典按照 ETG.1510 规范实现,使用标准 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只读主站诊断数据(丢帧率、帧频、状态)

Identity Object (0x1018)

子索引说明
0x01Vendor ID
0x02Product Code
0x03Revision Number
0x04Serial Number

Configuration Data (0x8nnn) — 从站配置

地址计算

从站 n 的配置数据索引为 0x8000 + (n-1)。例如从站 1 = 0x8000,从站 2 = 0x8001。

子索引名称类型读写说明
0x00Number of Entriesbyte只读固定 40
0x01Fixed Station Addressuint16只读配置地址(ConfigAddr)
0x02Typestring只读设备类型字符串
0x03Namestring只读设备名称
0x04Device Typeuint32只读设备类型编码
0x05Vendor IDuint32只读厂商 ID
0x06Product Codeuint32只读产品代码
0x07Revision Numberuint32只读修订号
0x08Serial Numberuint32只读序列号
0x21Mailbox Out Sizeuint16只读SM0 邮箱输出大小
0x22Mailbox In Sizeuint16只读SM1 邮箱输入大小
0x23Link Statusbyte只读端口链路状态
0x24Link Presetbyte只读端口链路预设
0x25Flagsbyte只读从站标志(Bit3: 热连接组成员)
0x26Port Physicsuint16只读端口物理类型
0x27Mailbox Protocolsuint16只读支持的邮箱协议(CoE=0x04, FoE=0x08 等)
0x28Diag History Supportedbyte只读是否支持 0x10F3 诊断历史对象

Information Data (0x9nnn) — 从站检测信息

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

地址计算

从站 n 的检测信息索引为 0x9000 + (n-1)。例如从站 1 = 0x9000,从站 2 = 0x9001。

子索引名称类型读写说明
0x00Number of Entriesbyte只读固定 32
0x01Station Addressuint16只读实际配置地址
0x05Vendor IDuint32只读检测到的厂商 ID
0x06Product Codeuint32只读检测到的产品代码
0x07Revision Numberuint32只读检测到的修订号
0x08Serial Numberuint32只读检测到的序列号
0x20DL Statusuint16只读DL Status 寄存器(ESC 0x0110-0x0111)

Diagnosis Data (0xAnnn) — 从站诊断

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

地址计算

从站 n 的诊断数据索引为 0xA000 + (n-1)。例如从站 1 = 0xA000,从站 2 = 0xA001。

子索引名称类型读写说明
0x00Number of Entriesbyte只读固定 19
0x01AL Statusuint16只读当前 AL 状态
0x02AL Controluint16可写写入时同步到从站
0x03Last AL Status Codeuint16只读最近一次 AL 错误码(ESC 0x0134)
0x04Link Conn. Statusbyte只读端口链路连接状态
0x05Link Controlbyte只读链路控制(DL Control 寄存器 0x0101)
0x06Fixed Addr Conn. Port 0uint16只读Port 0 连接的从站配置地址
0x07Fixed Addr Conn. Port 1uint16只读Port 1 连接的从站配置地址
0x08Fixed Addr Conn. Port 2uint16只读Port 2 连接的从站配置地址
0x09Fixed Addr Conn. Port 3uint16只读Port 3 连接的从站配置地址
0x0AFrame Error Port 0uint32只读Port 0 帧错误计数
0x0BFrame Error Port 1uint32只读Port 1 帧错误计数
0x0CFrame Error Port 2uint32只读Port 2 帧错误计数
0x0DFrame Error Port 3uint32只读Port 3 帧错误计数
0x0ECyclic WC Error Counteruint32只读周期性工作计数器错误
0x0FSlave Not Present Counteruint32只读从站不在线计数
0x10Abnormal State Change Counteruint32只读异常状态变化计数
0x11Disable Auto Link Controlbyte只读自动链路控制禁用标志
0x12Last CoE/SoE Protocol Erroruint32只读最近一次 CoE/SoE 协议错误码
0x13New Diag Messagesbyte只读是否有新诊断消息(通过 0x10F3 检测)

主站身份

GetMasterIdentity()

BOOL GetMasterIdentity(uint16_t master_index, ec_master_identity_t* identity);

获取主站身份信息。

参数:

  • master_index (uint16_t) — 主站索引
  • identity (ec_master_identity_t*) — 输出身份信息

返回值:

  • BOOL — 成功返回 TRUE

ec_master_identity_t

typedef struct {
uint32_t VendorId; /* 厂商 ID */
uint32_t ProductCode; /* 产品代码 */
uint32_t RevisionNo; /* 修订号 */
uint32_t SerialNo; /* 序列号 */
char DeviceName[64]; /* 设备名称 */
char HwVersion[32]; /* 硬件版本 */
char SwVersion[32]; /* 软件版本 */
} ec_master_identity_t;

主站诊断数据 (0xF120)

子索引名称类型读写说明
0x00Number of Entriesbyte只读固定 16
0x01Cyclic Lost Framesuint32只读周期性丢帧率(百分比 x 100)
0x02Acyclic Lost Framesuint32只读非周期性丢帧率(当前返回 0)
0x03Cyclic Frames/Seconduint32只读每秒周期帧数
0x04Acyclic Frames/Seconduint32只读每秒非周期帧数(当前返回 0)
0x10Master Stateuint16只读主站当前 EtherCAT 状态

GetMasterDiagData()

BOOL GetMasterDiagData(uint16_t master_index, ec_master_diag_data_t* diag);

获取主站诊断数据(ETG.1510 0xF120)。

参数:

  • master_index (uint16_t) — 主站索引
  • diag (ec_master_diag_data_t*) — 输出诊断数据

返回值:

  • BOOL — 成功返回 TRUE

ec_master_diag_data_t

typedef struct {
uint32_t CyclicLostFrames; /* 周期帧丢失率 (百分比 x 100) */
uint32_t AcyclicLostFrames; /* 非周期帧丢失率 */
uint32_t CyclicFramesPerSec; /* 周期帧频率 (帧/秒) */
uint32_t AcyclicFramesPerSec; /* 非周期帧频率 (帧/秒) */
uint16_t MasterState; /* 主站状态 */
} ec_master_diag_data_t;

0xF200 — 诊断接口控制

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

ETG.1510 索引常量

master/diagnostics.h 中定义的对象索引宏:

对象
ETG1510_DEVICE_TYPE0x1000Device Type
ETG1510_DEVICE_NAME0x1008Manufacturer Device Name
ETG1510_HW_VERSION0x1009Hardware Version
ETG1510_SW_VERSION0x100ASoftware Version
ETG1510_IDENTITY0x1018Identity Object
ETG1510_CONFIG_DATA_BASE0x8000从站配置数据基地址
ETG1510_INFO_DATA_BASE0x9000从站信息数据基地址
ETG1510_DIAG_DATA_BASE0xA000从站诊断数据基地址
ETG1510_DETECT_MODULES0xF002Detect Modules Command
ETG1510_MASTER_DIAG_DATA0xF120Master Diag Data
ETG1510_DIAG_INTERFACE_CTRL0xF200Diag Interface Control

通用 OD 访问

下列函数包装 SDO 路由, 让上层用同一接口访问主站对象字典任意索引. 0x1018 / 0xF120 自动路由到 GetMasterIdentity / GetMasterDiagData 快路径; 其他索引经 SDOread/SDOwrite 走标准 ETG.1510 §6.4 主站 OD 通道.

diagnostics_etg1510_read()

int diagnostics_etg1510_read(uint16_t master_index, uint16_t index,
uint8_t subindex, uint8_t* outBuf, int bufSize);

通过 ETG.1510 OD 读取主站对象 (SDO Upload 包装).

参数:

  • master_index (uint16_t) — 主站索引
  • index (uint16_t) — OD 索引 (0x1000-0xFFFF)
  • subindex (uint8_t) — OD 子索引
  • outBuf (uint8_t*) — 输出缓冲区
  • bufSize (int) — 缓冲区大小

返回值:

  • int — 实际写入字节数; -1=参数错误; -2=SDO 失败; -3=缓冲区不足; -10=动态加载路径 (改用 SDOread)

diagnostics_etg1510_write()

int diagnostics_etg1510_write(uint16_t master_index, uint16_t index,
uint8_t subindex, const uint8_t* data, int len);

通过 ETG.1510 OD 写入主站对象 (SDO Download 包装). 适用于 0xF200 Diag Interface Control, 0xF002 Detect Modules 等可写主站对象.

返回值:

  • int0 成功; -1 参数错误; -2 SDO 失败 (从站 Abort); -10 动态加载路径

示例:

/* 写 0xF200:0x10 = 1 复位主站诊断计数 */
uint8_t one = 1;
diagnostics_etg1510_write(mi, 0xF200, 0x10, &one, 1);

/* 读 0x100A 软件版本字符串 */
uint8_t buf[32] = {0};
int n = diagnostics_etg1510_read(mi, 0x100A, 0x00, buf, sizeof(buf));
if (n > 0) printf("SW Version: %s\n", buf);

AL 状态码分类

diagnostics_classify_al_error()

DarraAlErrorClass diagnostics_classify_al_error(uint16_t alStatusCode);

按 ETG.1020 把 AL Status Code 归到大类, 方便 UI 分组展示告警.

返回值:

  • DarraAlErrorClass — 错误大类枚举

相关结构:

typedef enum {
AL_ERR_NONE = 0,
AL_ERR_GENERAL = 1, /* 0x0001-0x000F 通用错误 */
AL_ERR_STARTUP = 2, /* 0x0010-0x001F 启动 */
AL_ERR_MAILBOX = 3, /* 0x0020-0x002F 邮箱 */
AL_ERR_WATCHDOG = 4, /* 0x0030-0x003F 看门狗 */
AL_ERR_SYNC = 5, /* 0x0040-0x004F 同步 */
AL_ERR_DC = 6, /* 0x0050-0x005F DC */
AL_ERR_MBX_EOE = 7, /* 0x0060-0x006F EoE 邮箱 */
AL_ERR_UNKNOWN = 99
} DarraAlErrorClass;

完整示例

#define DYNAMIC_LOAD
#include "ethercat.h"
#include <stdio.h>

int main(void)
{
dll_t dll;
LOAD_DLL(&dll, "Darra.Core.dll");
uint16_t master = dll.Initialize();
dll.SetNetwork(master, "\\Device\\NPF_{...}", "");
dll.SetStateSequence(master, EC_STATE_OPERATIONAL, 10000);
dll.Start(master);

/* ===== 读取主站身份 (0x1018) ===== */
ec_master_identity_t id;
if (dll.GetMasterIdentity(master, &id)) {
printf("=== 主站信息 (0x1018) ===\n");
printf("设备名称: %s\n", id.DeviceName);
printf("软件版本: %s\n", id.SwVersion);
printf("硬件版本: %s\n", id.HwVersion);
printf("VendorId: 0x%08X\n", id.VendorId);
printf("ProductCode: 0x%08X\n", id.ProductCode);
printf("RevisionNo: 0x%08X\n", id.RevisionNo);
printf("SerialNo: 0x%08X\n", id.SerialNo);
}

/* ===== 读取主站诊断数据 (0xF120) ===== */
ec_master_diag_data_t diag;
if (dll.GetMasterDiagData(master, &diag)) {
printf("\n=== 主站诊断 (0xF120) ===\n");
printf("周期帧频率: %u Hz\n", diag.CyclicFramesPerSec);
printf("非周期帧频率: %u Hz\n", diag.AcyclicFramesPerSec);
printf("周期帧丢失率: %.2f%%\n", diag.CyclicLostFrames / 100.0);
printf("主站状态: 0x%04X\n", diag.MasterState);
}

/* ===== 遍历所有从站诊断数据 (0xAnnn) ===== */
/* slave_count 来自 SetNetwork 返回值 */
printf("\n=== 从站诊断 (0xAnnn) ===\n");

for (uint16_t i = 1; i <= slave_count; i++) {
char name[128];
dll.GetSlaveName(master, i, name, sizeof(name));

/* 读取 AL Status 和错误码 */
uint16_t al_status = dll.GetSlaveState(master, i);
uint16_t al_code = dll.GetSlaveALStatusCode(master, i);

/* 读取链路质量 */
int16_t link_quality = dll.GetSlaveLinkQuality(master, i);

printf("从站 %d [%s]: AL=0x%04X, Code=0x%04X, 链路=%d%%\n",
i, name, al_status, al_code, link_quality);
}

/* ===== PDO 丢帧统计(按组) ===== */
printf("\n=== PDO 丢帧统计 ===\n");
for (uint8_t g = 0; g < 8; g++) {
uint32_t total = 0, consecutive = 0, max_consecutive = 0;
dll.GetPDOFrameLossStats(master, g, &total, &consecutive, &max_consecutive);
if (total > 0 || dll.GetGroupSlaveCount(master, g) > 0) {
printf("组 %d: 累计=%u, 连续=%u, 最大连续=%u\n",
g, total, consecutive, max_consecutive);
}
}

dll.Stop(master);
dll.Dispose(master);
UNLOAD_DLL(&dll);
return 0;
}