主站对象字典 (Master OD)
符合 ETG.1510 标准的主站对象字典,提供主站身份信息和诊断数据。
主站对象字典按照 ETG.1510 规范实现,使用标准 CoE 索引约定。配合邮箱网关使用,可实现远程诊断工具对主站的标准访问。
对象索引总览
| 索引 | 名称 | 子索引数 | 读写 | 说明 |
|---|---|---|---|---|
| 0x1000 | Device Type | 0 | 只读 | 0x00001389(EtherCAT Master) |
| 0x1008 | Device Name | 0 | 只读 | "Darra EtherCAT Master" |
| 0x1009 | Hardware Version | 0 | 只读 | x64 |
| 0x100A | Software Version | 0 | 只读 | SDK 版本号 |
| 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 | 只读 | 主站诊断数据(丢帧率、帧频、状态) |
Identity Object (0x1018)
| 子索引 | 说明 |
|---|---|
| 0x01 | Vendor ID |
| 0x02 | Product Code |
| 0x03 | Revision Number |
| 0x04 | Serial Number |
Configuration Data (0x8nnn) — 从站配置
从站 n 的配置数据索引为 0x8000 + (n-1)。例如从站 1 = 0x8000,从站 2 = 0x8001。
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0x00 | Number of Entries | byte | 只读 | 固定 40 |
| 0x01 | Fixed Station Address | uint16 | 只读 | 配置地址(ConfigAddr) |
| 0x02 | Type | string | 只读 | 设备类型字符串 |
| 0x03 | Name | string | 只读 | 设备名称 |
| 0x04 | Device Type | uint32 | 只读 | 设备类型编码 |
| 0x05 | Vendor ID | uint32 | 只读 | 厂商 ID |
| 0x06 | Product Code | uint32 | 只读 | 产品代码 |
| 0x07 | Revision Number | uint32 | 只读 | 修订号 |
| 0x08 | Serial Number | uint32 | 只读 | 序列号 |
| 0x21 | Mailbox Out Size | uint16 | 只读 | SM0 邮箱输出大小 |
| 0x22 | Mailbox In Size | uint16 | 只读 | SM1 邮箱输入大小 |
| 0x23 | Link Status | byte | 只读 | 端口链路状态 |
| 0x24 | Link Preset | byte | 只读 | 端口链路预设 |
| 0x25 | Flags | byte | 只读 | 从站标志(Bit3: 热连接组成员) |
| 0x26 | Port Physics | uint16 | 只读 | 端口物理类型 |
| 0x27 | Mailbox Protocols | uint16 | 只读 | 支持的邮箱协议(CoE=0x04, FoE=0x08 等) |
| 0x28 | Diag History Supported | byte | 只读 | 是否支持 0x10F3 诊断历史对象 |
Information Data (0x9nnn) — 从站检测信息
每个从站对应一个 0x9nnn 对象,包含运行时检测到的实际信息。
从站 n 的检测信息索引为 0x9000 + (n-1)。例如从站 1 = 0x9000,从站 2 = 0x9001。
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0x00 | Number of Entries | byte | 只读 | 固定 32 |
| 0x01 | Station Address | uint16 | 只读 | 实际配置地址 |
| 0x05 | Vendor ID | uint32 | 只读 | 检测到的厂商 ID |
| 0x06 | Product Code | uint32 | 只读 | 检测到的产品代码 |
| 0x07 | Revision Number | uint32 | 只读 | 检测到的修订号 |
| 0x08 | Serial Number | uint32 | 只读 | 检测到的序列号 |
| 0x20 | DL Status | uint16 | 只读 | DL Status 寄存器(ESC 0x0110-0x0111) |
Diagnosis Data (0xAnnn) — 从站诊断
每个从站对应一个 0xAnnn 对象,包含实时诊断数据。每次读取时自动更新。
从站 n 的诊断数据索引为 0xA000 + (n-1)。例如从站 1 = 0xA000,从站 2 = 0xA001。
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0x00 | Number of Entries | byte | 只读 | 固定 19 |
| 0x01 | AL Status | uint16 | 只读 | 当前 AL 状态 |
| 0x02 | AL Control | uint16 | 可写 | 写入时同步到从站 |
| 0x03 | Last AL Status Code | uint16 | 只读 | 最近一次 AL 错误码(ESC 0x0134) |
| 0x04 | Link Conn. Status | byte | 只读 | 端口链路连接状态 |
| 0x05 | Link Control | byte | 只读 | 链路控制(DL Control 寄存器 0x0101) |
| 0x06 | Fixed Addr Conn. Port 0 | uint16 | 只读 | Port 0 连接的从站配置地址 |
| 0x07 | Fixed Addr Conn. Port 1 | uint16 | 只读 | Port 1 连接的从站配置地址 |
| 0x08 | Fixed Addr Conn. Port 2 | uint16 | 只读 | Port 2 连接的从站配置地址 |
| 0x09 | Fixed Addr Conn. Port 3 | uint16 | 只读 | Port 3 连接的从站配置地址 |
| 0x0A | Frame Error Port 0 | uint32 | 只读 | Port 0 帧错误计数 |
| 0x0B | Frame Error Port 1 | uint32 | 只读 | Port 1 帧错误计数 |
| 0x0C | Frame Error Port 2 | uint32 | 只读 | Port 2 帧错误计数 |
| 0x0D | Frame Error Port 3 | uint32 | 只读 | Port 3 帧错误计数 |
| 0x0E | Cyclic WC Error Counter | uint32 | 只读 | 周期性工作计数器错误 |
| 0x0F | Slave Not Present Counter | uint32 | 只读 | 从站不在线计数 |
| 0x10 | Abnormal State Change Counter | uint32 | 只读 | 异常状态变化计数 |
| 0x11 | Disable Auto Link Control | byte | 只读 | 自动链路控制禁用标志 |
| 0x12 | Last CoE/SoE Protocol Error | uint32 | 只读 | 最近一次 CoE/SoE 协议错误码 |
| 0x13 | New Diag Messages | byte | 只读 | 是否有新诊断消息(通过 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)
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0x00 | Number of Entries | byte | 只读 | 固定 16 |
| 0x01 | Cyclic Lost Frames | uint32 | 只读 | 周期性丢帧率(百分比 x 100) |
| 0x02 | Acyclic Lost Frames | uint32 | 只读 | 非周期性丢帧率(当前返回 0) |
| 0x03 | Cyclic Frames/Second | uint32 | 只读 | 每秒周期帧数 |
| 0x04 | Acyclic Frames/Second | uint32 | 只读 | 每秒非周期帧数(当前返回 0) |
| 0x10 | Master State | uint16 | 只读 | 主站当前 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 — 诊断接口控制
| 子索引 | 名称 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 0x00 | Number of Entries | byte | 只读 | 固定 16 |
| 0x10 | Reset Diag Info | byte | 可写 | 写入 1 复位所有从站和主站的诊断计数器(上升沿触发) |
ETG.1510 索引常量
master/diagnostics.h 中定义的对象索引宏:
| 宏 | 值 | 对象 |
|---|---|---|
| ETG1510_DEVICE_TYPE | 0x1000 | Device Type |
| ETG1510_DEVICE_NAME | 0x1008 | Manufacturer Device Name |
| ETG1510_HW_VERSION | 0x1009 | Hardware Version |
| ETG1510_SW_VERSION | 0x100A | Software Version |
| ETG1510_IDENTITY | 0x1018 | Identity Object |
| ETG1510_CONFIG_DATA_BASE | 0x8000 | 从站配置数据基地址 |
| ETG1510_INFO_DATA_BASE | 0x9000 | 从站信息数据基地址 |
| ETG1510_DIAG_DATA_BASE | 0xA000 | 从站诊断数据基地址 |
| ETG1510_DETECT_MODULES | 0xF002 | Detect Modules Command |
| ETG1510_MASTER_DIAG_DATA | 0xF120 | Master Diag Data |
| ETG1510_DIAG_INTERFACE_CTRL | 0xF200 | Diag 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 等可写主站对象.
返回值:
int—0成功;-1参数错误;-2SDO 失败 (从站 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;
}