跳到主要内容

从站诊断

每个从站提供独立的诊断函数,可查询端口错误、冗余、DC 同步、链路质量等信息。

从站基础属性

从站状态(GetSlaveStateGetSlaveALStatusCode)等基础属性请参考 属性与状态机

配合事件使用

建议通过 事件 驱动异常处理(如 SlaveStateChangedSlaveOfflineDCSyncLost),而非轮询。 直接读取从站诊断函数适用于 UI 显示等场景。

主站级诊断

全局通信统计、丢包率、PDO 丢帧汇总请参考 主站诊断

功能概览

功能函数说明
通信诊断ReadSlavePortErrorCounters()ESC 端口错误计数器 (RX/帧/链路)
冗余诊断GetSlaveRedundancyActivated()冗余激活、主/冗余线路断路检测
DC 同步GetSlaveSyncWindowStatus()同步状态、时间差
链路质量GetSlaveLinkQuality()链路质量百分比 (0-100)
从站详细信息GetSlaveDetailedInfo()单从站完整快照指针
端口断线事件RegisterSlavePortLinkChangedP0-P3 link 翻转事件

ESC 端口错误结构:

typedef struct {
uint8_t RxErrorCount[4]; /* 各端口 RX 错误计数 [Port0-3], 物理层 CRC 或编码错误 */
uint8_t InvalidFrameCount[4]; /* 各端口无效帧计数 [Port0-3], 帧格式不正确 */
uint8_t LostLinkCount[4]; /* 各端口链路丢失计数 [Port0-3], 物理连接断开次数 */
} ec_esc_port_error_stats_t;

通信诊断

BOOL ReadSlavePortErrorCounters(uint16_t master_index, uint16_t slave_index,
uint8_t* rx_error, uint8_t* invalid_frame, uint8_t* lost_link);
BOOL ResetSlavePortErrorCounters(uint16_t master_index, uint16_t slave_index);
int ReadAllSlavePortErrorCounters(uint16_t master_index);
void* GetSlavePortErrorStats(uint16_t master_index, uint16_t slave_index);
void UpdateDiagnosticsWithESCErrors(uint16_t master_index);

ReadSlavePortErrorCounters() 读取从站各端口(4 字节数组对应 P0-P3)的 RX 错误、无效帧、链路丢失计数。ResetSlavePortErrorCounters() 重置单从站,ReadAllSlavePortErrorCounters() 一次读取所有从站并返回成功数量。GetSlavePortErrorStats() 返回内部统计指针(无需释放)。

备注

ReadSlavePortErrorCounters() 需实时读取从站,不建议高频调用(建议 ≥ 100ms 间隔)。 冗余和 DC 状态查询函数为"始终活跃",无需启用诊断模块。

示例:

uint8_t rx[4], inv[4], lost[4];
if (dll.ReadSlavePortErrorCounters(master, 1, rx, inv, lost)) {
for (int p = 0; p < 4; p++) {
if (rx[p] || inv[p] || lost[p])
printf("从站1 P%d: RX=%u Inv=%u Lost=%u\n", p, rx[p], inv[p], lost[p]);
}
}

冗余诊断

BOOL GetSlaveRedundancyActivated(uint16_t master_index, uint16_t slave_index);
BOOL GetSlavePrimaryLinkBroken(uint16_t master_index, uint16_t slave_index);
BOOL GetSlaveSecondaryLinkBroken(uint16_t master_index, uint16_t slave_index);

仅在主站启用冗余时有意义,仅检测物理断线,不含 CRC 故障。

函数说明
GetSlaveRedundancyActivated冗余被激活(从站未丢失,但网络中存在断线,冗余机制正在工作)
GetSlavePrimaryLinkBroken主线路断路(从主端口 Port0 到该从站的路径上存在断线)
GetSlaveSecondaryLinkBroken冗余线路断路(从副端口 Port1 反向到该从站的路径上存在断线)
主站级监控

全局冗余状态和断线点请参考 主站诊断 - 冗余状态

示例:

for (uint16_t s = 1; s <= slave_count; s++) {
if (!dll.GetSlaveRedundancyActivated(master, s)) continue;
printf("从站 %d: 冗余激活", s);
if (dll.GetSlavePrimaryLinkBroken(master, s)) printf(", 主线路断路");
if (dll.GetSlaveSecondaryLinkBroken(master, s)) printf(", 冗余线路断路");
printf("\n");
}

DC 同步

BOOL GetSlaveSyncWindowStatus(uint16_t master_index, uint16_t slave_index,
int* diff_ns, int* max_diff_ns, int* min_diff_ns,
BOOL* in_sync, uint32_t* out_of_sync_count);
void ResetSlaveSyncWindowStats(uint16_t master_index, uint16_t slave_index);
int16_t GetSlaveLinkQuality(uint16_t master_index, uint16_t slave_index);

GetSlaveSyncWindowStatus() 返回当前/最大/最小偏差、是否在同步窗口内(阈值由主站 SetSyncWindowThreshold() 控制)、累计失同步次数。GetSlaveLinkQuality() 返回链路质量百分比(0-100,综合 RxError + InvalidFrame + WKC 异常计算)。详见 DC 配置主站诊断 - DC 同步

完整示例

#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();
uint16_t slave_count = dll.SetNetwork(master, "\\Device\\NPF_{GUID}", "");
dll.SetStateSequence(master, EC_STATE_OPERATIONAL, 10000);
dll.Start(master);

for (uint16_t s = 1; s <= slave_count; s++) {
printf("--- 从站 %d ---\n", s);

/* 端口错误 */
uint8_t rx[4], inv[4], lost[4];
if (dll.ReadSlavePortErrorCounters(master, s, rx, inv, lost)) {
for (int p = 0; p < 4; p++)
if (rx[p] || inv[p] || lost[p])
printf(" P%d: RX=%u Inv=%u Lost=%u\n", p, rx[p], inv[p], lost[p]);
}

/* 链路质量 */
printf(" 链路质量: %d%%\n", dll.GetSlaveLinkQuality(master, s));

/* 冗余 */
if (dll.GetSlaveRedundancyActivated(master, s))
printf(" 冗余激活: 主断=%d, 副断=%d\n",
dll.GetSlavePrimaryLinkBroken(master, s),
dll.GetSlaveSecondaryLinkBroken(master, s));

/* DC 同步 */
int diff, max_d, min_d; BOOL sync; uint32_t oos;
if (dll.GetSlaveSyncWindowStatus(master, s, &diff, &max_d, &min_d, &sync, &oos))
printf(" DC: 偏差=%dns, 同步=%s, 失步=%u\n",
diff, sync ? "是" : "否", oos);
}

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