属性与状态机
属性
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 基本信息 | MasterNumber | ushort | 只读 | 主站实例编号 |
SlaveCount | int | 只读 | 网络中检测到的从站数量 | |
Slaves | List<Slave> | 只读 | 从站列表(索引 0 起始) | |
IsDisposed | bool | 只读 | 主站是否已被释放 | |
| 网络与链路 | PrimaryNetworkInfo | NetworkInfo | 只读 | 主网络适配器信息 |
RedundantNetworkInfo | NetworkInfo | 只读 | 冗余网络适配器信息 | |
LinkState | EcLinkState | 只读 | 网络链路状态 | |
| 错误码 | ErrorCode | EcALState | 只读 | 异常时的自动报警错误码 |
| 从站分组 | Groups | SlaveGroupAccessor | 只读 | 组索引器 — Groups[g] 获取该组从站列表,Groups[g][i] 获取组内第 i 个从站 |
ActiveGroupCount | byte | 只读 | 活跃组数量(映射后有效) | |
| IO 映射 | Obytes | uint | 只读 | 总输出字节数 |
Ibytes | uint | 只读 | 总输入字节数 | |
Obits | ushort | 只读 | 总输出位数 | |
Ibits | ushort | 只读 | 总输入位数 | |
| DC | HasDC | bool | 只读 | 网络中是否有支持 DC 的从站。详见 [DC 与周期](./dc) |
EcLinkState 枚举值
public enum EcLinkState : byte
{
Disconnected = 0, // 无连接
Connected = 1, // 主网口和冗余网口都连接
PrimaryOnly = 3, // 仅主网口连接
SecondaryOnly = 4 // 仅冗余网口连接
}
EcALState 枚举值
public enum EcALState : int
{
NoError = 0x0000, // 无错误
UnspecifiedError = 0x0001, // 未指定错误
NoMemory = 0x0002, // 内存不足
InvalidDeviceSetup = 0x0003, // 无效设备设置
InvalidRevision = 0x0004, // 版本不匹配
SiiEepromMismatch = 0x0006, // SII/EEPROM 不匹配
FirmwareUpdateFailed = 0x0007, // 固件更新失败
LicenseError = 0x000E, // 许可证错误
InvalidStateChange = 0x0011, // 无效状态切换
UnknownRequestedState = 0x0012, // 未知状态请求
BootstrapNotSupported = 0x0013, // 不支持 Bootstrap
NoValidFirmware = 0x0014, // 无有效固件
InvalidMailboxConfig = 0x0015, // 无效邮箱配置 (SM0/SM1)
InvalidSyncManagerConfig = 0x0017, // 无效同步管理器配置
NoValidInputs = 0x0018, // 无有效输入
NoValidOutputs = 0x0019, // 无有效输出
SyncError = 0x001A, // 同步错误
SyncManagerWatchdog = 0x001B, // SM 看门狗
InvalidOutputConfig = 0x001D, // 无效输出配置
InvalidInputConfig = 0x001E, // 无效输入配置
InvalidWatchdogConfig = 0x001F, // 无效看门狗配置
NeedsColdStart = 0x0020, // 需要冷启动
NeedsInit = 0x0021, // 需要 Init
NeedsPreOp = 0x0022, // 需要 PreOp
NeedsSafeOp = 0x0023, // 需要 SafeOp
InvalidInputMapping = 0x0024, // 无效输入映射
InvalidOutputMapping = 0x0025, // 无效输出映射
InconsistentSettings = 0x0026, // 设置不一致
FreerunNotSupported = 0x0027, // 不支持自由运行
SyncNotSupported = 0x0028, // 不支持同步
CycleTimeTooSmall = 0x002E, // 周期时间过小
InvalidDcSyncConfig = 0x0030, // 无效 DC 同步配置
PllError = 0x0032, // PLL 错误
DcSyncIOError = 0x0033, // DC 同步 IO 错误
DcSyncTimeout = 0x0034, // DC 同步超时
MailboxAoe = 0x0041, // AoE 邮箱错误
MailboxCoe = 0x0043, // CoE 邮箱错误
MailboxFoe = 0x0044, // FoE 邮箱错误
MailboxSoe = 0x0045, // SoE 邮箱错误
EepromNoAccess = 0x0050, // EEPROM 无法访问
EepromError = 0x0051, // EEPROM 错误
ExternalHardwareNotReady = 0x0052, // 外部硬件未就绪
SlaveRestarted = 0x0060, // 从站已重启
SupplyVoltageTooLow = 0x0080, // 电压过低
SupplyVoltageTooHigh = 0x0081, // 电压过高
TemperatureTooLow = 0x0082, // 温度过低
TemperatureTooHigh = 0x0083, // 温度过高
Unknown = 0xFFFF // 未知错误
}
状态机管理
State
EtherCAT 当前状态 (只读)。切换状态请调用 SetState(...)。
相关结构:
public enum EcState : byte
{
None = 0x00,
Init = 0x01,
PreOp = 0x02,
Boot = 0x03,
SafeOp = 0x04,
OP = 0x08,
Ack = 0x10,
Error = 0x10
}
示例:
if (master.State == EcState.OP)
Console.WriteLine("主站处于运行状态");
- SDK 中的所有切换状态机方法 , 均符合 EtherCAT 标准状态机流程,协议层自动处理。
- 请在启动前导入或设置正确的配置。
- 如需返回更详细的错误信息,请使用
SetState(state, out string err)重载。
SetState(EcState state)
public bool SetState(EcState state)
切换主站到目标状态。内部自动按 ETG 状态机链 (Init↔PreOp↔SafeOp↔OP) 跨多级一次到位,自动应用各步启动参数。进入 SafeOp/OP 时自动启动 PDO 线程,每步默认 5s 超时。
参数:
state(EcState) — 目标状态
返回值:
bool—true切换成功,false失败
SDK 在状态切换内部自动执行 3 次重试 (每次失败后等待 1.5s),用于吸收硬件偶发抖动 (PHY PLL 抖动等)。用户不需要自行包装重试逻辑。
切换到 SafeOp 时,SDK 自动按 ETG 标准为非 DC 从站配置同步循环计数阈值与 SyncManager 同步类型 (FreeRun 兜底),应用层无需手动写。
DC 从站跳过此自动配置 (避免与 DC 时基冲突)。如需自定义同步策略,应在切到 SafeOp 之后再覆盖。写入失败时容忍继续,不阻塞 SafeOp 转换。
示例:
if (!master.SetState(EcState.OP))
Console.WriteLine("状态切换失败");
SetState(EcState state, out string error)
public bool SetState(EcState state, out string error)
切换主站到目标状态,并通过 error 输出失败原因(用于诊断)。成功时 error 为 null。重试与 SafeOp 自动 SDO 行为同上。
参数:
state(EcState) — 目标状态error(out string) — 失败时的中文错误描述,成功为null
返回值:
bool—true切换成功,false失败
示例:
if (!master.SetState(EcState.OP, out string err))
Console.WriteLine($"状态切换失败: {err}");
SetStateAsync(EcState state, CancellationToken)
public Task<bool> SetStateAsync(EcState state, CancellationToken ct = default)
异步版状态切换,不阻塞调用线程。支持取消令牌。重试与 SafeOp 自动 SDO 行为同上。
参数:
state(EcState) — 目标状态ct(CancellationToken) — 取消令牌(可选)
返回值:
Task<bool>—true切换成功,false失败
示例:
bool ok = await master.SetStateAsync(EcState.OP, cancellationToken);
if (!ok)
Console.WriteLine("状态切换失败");
Stop()
public bool Stop()
停止主站,切换到 PRE_OP 状态。
Abort()
public static void Abort()
中断协议层所有阻塞操作(如 SetState()、Build() 中的 SetNetwork 等)。可安全地从任意线程调用。
示例:
// 用户点击取消按钮时中断正在进行的状态切换
DarraEtherCAT.Abort();
WaitForState(EcState state, int timeoutMs = 10000, int pollIntervalMs = 50)
public bool WaitForState(EcState state, int timeoutMs = 10000, int pollIntervalMs = 50)
轮询等待主站到达指定状态。不发起状态切换, 仅等待已请求的转换完成 / PDO 流稳定确认。常用于 SetState 异步触发后的确认窗口, 或 PDO 启动后短暂等待 OP 稳定。
参数:
state(EcState) — 目标状态timeoutMs(int) — 最大等待时间(毫秒),默认 10000mspollIntervalMs(int) — 轮询间隔(毫秒),默认 50ms
返回值:
bool— 在超时前到达目标状态返回true
示例:
master.SetState(EcState.OP);
// 最多等 5s 主站进入 OP
if (!master.WaitForState(EcState.OP, timeoutMs: 5000))
{
Console.WriteLine("主站未在 5s 内进入 OP");
}
WaitForSlaveState(int slaveNum, EcState state, int timeoutMs = 10000, int pollIntervalMs = 50)
public bool WaitForSlaveState(int slaveNum, EcState state, int timeoutMs = 10000, int pollIntervalMs = 50)
轮询等待单个从站到达指定状态。适用于 PDO 启动后对关键从站的状态确认。
参数:
slaveNum(int) — 从站编号(1-based)state(EcState) — 目标状态timeoutMs(int) — 最大等待时间(毫秒),默认 10000mspollIntervalMs(int) — 轮询间隔(毫秒),默认 50ms
返回值:
bool— 在超时前到达目标状态返回true
示例:
// 等从站 3 进入 OP, 最多 3s
if (!master.WaitForSlaveState(3, EcState.OP, timeoutMs: 3000))
{
Console.WriteLine($"从站 3 当前: {master.Slaves[2].State}");
}
GetTransitionTimeoutMs(EcState from, EcState to)
public int GetTransitionTimeoutMs(EcState from, EcState to)
查询某条状态转换的推荐最大等待时长(毫秒)。SDK 内部按 ESI / 配置 / ETG.1020 默认值兜底, 上层可读出该值用于自定义进度提示或测试断言。
参数:
from(EcState) — 起始状态to(EcState) — 目标状态
返回值:
int— 推荐超时(毫秒)
示例:
int initToPreOp = master.GetTransitionTimeoutMs(EcState.Init, EcState.PreOp);
Console.WriteLine($"Init→PreOp 推荐超时: {initToPreOp}ms");
过程数据看门狗
SetAllSlaveWatchdog(uint timeoutMs)
public int SetAllSlaveWatchdog(uint timeoutMs)
批量设置所有从站的过程数据看门狗超时。
参数:
timeoutMs(uint) — 超时时间(毫秒),0 = 禁用,最大 6553ms
返回值:
int— 成功设置的从站数量
单个从站的看门狗配置请使用 slave.SetWatchdog()。
示例:
int count = master.SetAllSlaveWatchdog(100);
Console.WriteLine($"已设置 {count} 个从站看门狗超时为 100ms");
SetAllSlavePdiWatchdog(uint timeoutMs)
public int SetAllSlavePdiWatchdog(uint timeoutMs)
批量设置所有从站的 PDI 看门狗超时。
参数:
timeoutMs(uint) — 超时时间(毫秒),0 = 禁用,最大 6553ms
返回值:
int— 成功设置的从站数量
单个从站的看门狗配置请使用 slave.SetPdiWatchdog()。
示例:
int count = master.SetAllSlavePdiWatchdog(100);
Console.WriteLine($"已设置 {count} 个从站 PDI 看门狗超时为 100ms");
诊断控制方法
ResetDiagnostics()
public void ResetDiagnostics()
重置主站诊断计数器。等同于调用 master.Diagnostics.Reset() 中的诊断重置部分。
ResetSlavePortErrorCounters(ushort slaveIndex)
public bool ResetSlavePortErrorCounters(ushort slaveIndex)
重置指定从站的端口错误计数器。
参数:
slaveIndex(ushort) — 从站索引(1-based)
返回值:
bool— 成功返回true
master.Diagnostics.Reset() 会同时重置主站诊断统计、所有从站端口错误计数器和 PDO 丢帧统计。
热插拔自修复
在断电重插/更换从站的场景下,SDK 自动识别身份不符并进入保护状态,避免错误设备被误纳入控制循环。事件流程见 SlaveIdentityMismatch 事件。
AcknowledgeSlaveReplacement(int slaveNum)
public bool AcknowledgeSlaveReplacement(int slaveNum)
用户确认从站替换完毕,触发 EtherCAT 识别状态机重新探测该从站。
调用时机: 订阅 master.Events.SlaveIdentityMismatch 接收到身份不符报警后,操作员检查/更换设备完毕,调用本方法让 SDK 重新检测。
行为:
- 若身份已纠正(换回正确设备 / 同型号升级 Revision)→ 自动恢复并触发
SlaveOnline事件 - 若身份仍不匹配 → 再次触发
SlaveIdentityMismatch,回到IDENT_REJECTED状态
参数:
slaveNum(int) — 从站编号(1-based,与配置一致)
返回值:
bool—true=已接受并复位 FSM;false=参数无效,或从站当前不在IDENT_REJECTED/FAILED状态(收到SlaveIdentityMismatch事件之前调用返回false)
在 SlaveIdentityMismatch 事件触发之前调用本方法无效。从站未进入保护状态时 SDK 会持续正常探测,无需手动确认。
示例:
master.Events.SlaveIdentityMismatch += (sender, args) =>
{
Console.WriteLine($"从站 {args.SlaveIndex} 身份不符: " +
$"期望 Vendor=0x{args.ExpectedVendor:X8}, 实际 Vendor=0x{args.ActualVendor:X8}");
// UI 弹窗: "请检查从站 N 的设备, 换回正确型号后点击确认"
if (ShowReplacementDialog(args.SlaveIndex))
{
bool ok = master.AcknowledgeSlaveReplacement(args.SlaveIndex);
if (!ok)
Console.WriteLine("确认失败: 从站不在 IDENT_REJECTED 状态");
}
};
SlaveOffline— 从站断电/断线(身份仍匹配),自动恢复并触发SlaveOnlineSlaveIdentityMismatch— 从站身份变了(换错设备 / 换同型号旧版本固件),需手动调AcknowledgeSlaveReplacement
生命周期
Close()
public void Close()
按完整收尾流程释放主站: 中止 DLL 阻塞调用 → 停 PDO 线程 → 限时 3 秒尝试切回 PreOp → 停诊断采样 → 释放邮箱网关 → Dispose(). 与直接 Dispose() 的区别在于先做"软停车"再硬释放, 推荐 GUI/Service 退出时调用.
示例:
master.Close();
VerifyStartupConfiguration(bool strictMode = false)
public StartupConfigurationVerifier.VerificationResult VerifyStartupConfiguration(bool strictMode = false)
按 ETG.1500 §5.5.2 比较加载的 ENI 配置与实际扫描到的从站身份, 返回逐站匹配明细. 未加载 XML 配置时直接返回 Success=true.
参数:
strictMode(bool) — 严格模式: 同时校验 RevisionNo 和 SerialNo, 默认false(仅校验 VendorId / ProductCode)
返回值:
VerificationResult—Success/Errors/Warnings/SlaveDetails四字段
相关结构:
public class VerificationResult
{
public bool Success { get; set; }
public List<string> Errors { get; set; }
public List<string> Warnings { get; set; }
public List<SlaveDetail> SlaveDetails { get; set; }
}
示例:
var result = master.VerifyStartupConfiguration(strictMode: false);
if (!result.Success)
foreach (var err in result.Errors) Console.WriteLine(err);
GetMasterClass()
public char GetMasterClass()
返回当前主站的 ETG.1500 实现类: 'A' = Class A (Full Featured), 'B' = Class B (Basic). Darra 默认返回 'A'.
返回值:
char—'A'/'B'
示例:
char cls = master.GetMasterClass();
Console.WriteLine($"Master Class: {cls}");
GetDiagnostics()
public SlaveDiagnosticsData GetDiagnostics()
返回全局诊断快照: 各从站端口链路状态 / 可达性 / 链路质量 + 主站累计帧错误 / 丢帧 / WKC 失配 / Tx-Rx 计数. 从 DLL 缓存零延迟读取, 不发 SDO 不发 FPRD.
返回值:
SlaveDiagnosticsData— 诊断数据对象, 失败返回null
示例:
var diag = master.GetDiagnostics();
if (diag != null)
{
Console.WriteLine($"主端口 Tx={diag.PrimaryPortTx}, Rx={diag.PrimaryPortRx}");
Console.WriteLine($"丢帧={diag.LostFrames}, WKC 失配={diag.TotalWkcMismatches}");
}
RebuildTopology()
public void RebuildTopology()
重建从站拓扑视图. 当从站列表发生变化 (热插拔 / 重新枚举) 后调用, 刷新 SlaveTopology 缓存的父子端口关系.
示例:
master.AcknowledgeSlaveReplacement(3);
master.RebuildTopology();
TopologyMismatchMessage
public string TopologyMismatchMessage { get; }
最近一次拓扑校验发现的错配信息. ENI 拓扑与实测拓扑不一致时由内部填充, 通常作为 Build 成功消息的尾部追加显示.
示例:
if (!string.IsNullOrEmpty(master.TopologyMismatchMessage))
Console.WriteLine(master.TopologyMismatchMessage);
ResetAllSyncWindowStats()
public void ResetAllSyncWindowStats()
清零所有从站的 DC 同步窗口统计 (jitter min/max/avg / 越界次数). 调用 DLL.ResetSlaveSyncWindowStats(MasterNumber, 0), 通常在切换工况或长时间运行后基线复位.
示例:
master.ResetAllSyncWindowStats();
DisableAutoStartup()
public DarraEtherCAT DisableAutoStartup()
显式禁用 AutoStartup. 默认行为下首次 SetState 会自动 EnableAutoStartup, 调用本方法可关闭这个自动启用 (例如纯 ENI/DENI 场景或测试场景), 同时清除 _pendingAutoStartup 防止 Build 阶段自动配置. 支持链式调用.
返回值:
DarraEtherCAT— 当前实例, 支持链式
示例:
var master = new DarraEtherCAT()
.SetENI("config.xml")
.DisableAutoStartup()
.Build();
静态工具
DarraEtherCAT.DLL_AbortAndReset()
public static void DLL_AbortAndReset()
紧急中断 DLL 网络操作并重置中断标志. 静态方法, 看门狗 / 守护线程在监测到主回调卡死时调用. 内部 AbortNetwork() → 100ms → ResetAbortNetwork(), 不需要主站实例.
示例:
if (watchdog.MissCount > 5)
DarraEtherCAT.DLL_AbortAndReset();
DarraEtherCAT.EmergencyCleanup()
public static void EmergencyCleanup()
进程崩溃 / 异常退出时直接关闭所有 WDK 网卡句柄. 不依赖 C# 对象状态, 不等待线程退出, 总耗时约 100ms (DLL 内部等待线程感知中止标志). 进程退出前必须调用, 否则下次启动可能因句柄泄漏无法打开网卡.
示例:
AppDomain.CurrentDomain.ProcessExit += (_, _) => DarraEtherCAT.EmergencyCleanup();
AppDomain.CurrentDomain.UnhandledException += (_, _) => DarraEtherCAT.EmergencyCleanup();
DarraEtherCAT.EnsureDriversRunning()
public static bool EnsureDriversRunning()
确保 DarraRT + DarraRT_Eth 两个内核驱动都处于 RUNNING 状态. 未运行的会尝试 StartService, 每个最长等 3 秒. GUI 主入口前置门, 返回 false 时应弹错并退出, 不允许进入主界面.
返回值:
bool—true= 两驱动均在跑;false= 任一驱动缺失或自动启动失败
示例:
if (!DarraEtherCAT.EnsureDriversRunning())
{
MessageBox.Show("内核驱动未运行, 请检查 DarraRT 安装");
return;
}
DarraEtherCAT.InitializeLogging()
public static void InitializeLogging()
显式拉起日志系统: 注册 DLL 日志回调 / 崩溃回调, 默认关闭 PDO/Mailbox/Debug 三类高频日志, 同时检测管理员权限 (非管理员弹一次警告). Init/Build 内部会自动调用, 一般无需手动.
示例:
DarraEtherCAT.InitializeLogging();
DarraEtherCAT.EnableMessageLogging(true);
DarraEtherCAT.EnableMessageLogging(bool enable = true)
public static void EnableMessageLogging(bool enable = true)
控制 LogView 是否显示 LogCategory.Message 类别 (初始化里程碑 / 进度信息). 默认关闭, 开启后可看到 Build/SetState 各阶段进度.
参数:
enable(bool) —true显示消息类日志, 默认true
示例:
DarraEtherCAT.EnableMessageLogging(true);
DarraEtherCAT.ActiveInstanceCount
public static int ActiveInstanceCount { get; }
当前已构建未释放的主站实例数. 多实例场景下用于上限校验.
DarraEtherCAT.MaxInstanceCount
public static int MaxInstanceCount { get; }
DLL 允许的主站实例上限 (DLL.GetMaxMasterInstances()). 受授权和可用隔离核心数限制.
示例:
if (DarraEtherCAT.ActiveInstanceCount >= DarraEtherCAT.MaxInstanceCount)
throw new InvalidOperationException("已达主站实例上限");
DarraEtherCAT.Logs
public static LogView Logs { get; }
全局日志视图. 用户只读, 内部数据自动维护. 支持 SetFilter 过滤类别, Updated 事件通知数据变化, 默认按操作 (SetState/SDO/FoE) 自动清空旧日志, 设 Logs.Retain = true 可保留全部.
示例:
var logs = DarraEtherCAT.Logs;
logs.SetFilter(LogCategory.Error, LogCategory.Warning);
logs.Updated += () => Console.WriteLine($"日志更新: {logs.Count} 条");
DarraEtherCAT.GetActiveGroupCount(ushort masterIndex = 1)
public static byte GetActiveGroupCount(ushort masterIndex = 1)
返回指定主站的活跃分组数量 (空组不计). 跨实例调用, 不需要持有 DarraEtherCAT 对象.
参数:
masterIndex(ushort) — 主站编号, 默认1
返回值:
byte— 活跃组数量
DarraEtherCAT.GetGroupActualWKC(ushort masterIndex, byte group)
public static ushort GetGroupActualWKC(ushort masterIndex, byte group)
读取某分组上一周期 PDO 交换的实际 WKC. 每组一个 LRW 报文, WKC 由组独立维护.
DarraEtherCAT.GetGroupExpectedWKC(ushort masterIndex, byte group)
public static ushort GetGroupExpectedWKC(ushort masterIndex, byte group)
读取某分组的期望 WKC (映射后固定不变). 用于与 GetGroupActualWKC 比较判断丢帧.
DarraEtherCAT.GetGroupDiag(ushort, byte, out ushort, out uint, out uint)
public static bool GetGroupDiag(ushort masterIndex, byte group,
out ushort consecutiveMiss, out uint totalFrames, out uint mismatchFrames)
获取某分组诊断三件套.
参数:
masterIndex(ushort) — 主站编号group(byte) — 分组号 (0-based)
返回值:
consecutiveMiss(ushort) — 连续 WKC 不足次数totalFrames(uint) — 累计 TX 帧数mismatchFrames(uint) — WKC 失配帧数bool— 调用成功返回true
示例:
byte n = DarraEtherCAT.GetActiveGroupCount(1);
for (byte g = 0; g < n; g++)
{
DarraEtherCAT.GetGroupDiag(1, g, out var miss, out var total, out var mis);
Console.WriteLine($"组 {g}: WKC={DarraEtherCAT.GetGroupActualWKC(1,g)}/" +
$"{DarraEtherCAT.GetGroupExpectedWKC(1,g)} 连续不足={miss} 总帧={total} 失配={mis}");
}
状态机工具
DarraEtherCAT.IsLegalEsmTransition(EcState from, EcState to)
public static bool IsLegalEsmTransition(EcState from, EcState to)
按 ETG.1000.6 §6.4.2 Table 52 判定状态转换是否合法. 合法包含 IP/PS/SO 升级 + OS/SP/PI 降级 + OP/OI/SI 跨级降级 + IB/BI Boot + 同状态. 非法包含 Init→SafeOp / Init→Op / PreOp→Op (跳级升级) / Boot→PreOp/SafeOp/Op.
参数:
from(EcState) — 起始状态to(EcState) — 目标状态
返回值:
bool— 合法返回true
示例:
if (!DarraEtherCAT.IsLegalEsmTransition(EcState.Init, EcState.OP))
Console.WriteLine("禁止 Init 直接跳到 OP, 必须逐级升");
DarraEtherCAT.GetLegalEsmTransitions(EcState from)
public static EcState[] GetLegalEsmTransitions(EcState from)
返回从指定状态出发可合法进入的所有目标状态.
参数:
from(EcState) — 起始状态
返回值:
EcState[]— 合法目标列表; 失败返回空数组
示例:
foreach (var s in DarraEtherCAT.GetLegalEsmTransitions(EcState.PreOp))
Console.WriteLine(s);
DarraEtherCAT.GetEsmDefaultTimeoutMs(EcState from, EcState to)
public static uint GetEsmDefaultTimeoutMs(EcState from, EcState to)
返回 ETG.1020 §9.4 Table 55 规定的 from→to 默认超时 (ms): IP=3000, PS=10000, SO=10000, OS=200, SP=200, PI/SI/OP/OI=5000, IB=10000, BI=5000. 返回 0 表示该转换非法.
示例:
uint ms = DarraEtherCAT.GetEsmDefaultTimeoutMs(EcState.PreOp, EcState.SafeOp);
// ms == 10000
DarraEtherCAT.IsKnownAlStatusCode(ushort code)
public static bool IsKnownAlStatusCode(ushort alStatusCode)
判定 AL Status Code 是否为 ETG.1000.6 §6.4.4 Table 58 / ETG.1020 标准定义. false 通常表示厂商特定错误码 (≥ 0x8000 或未列表).
DarraEtherCAT.ClassifyAlStatusCode(ushort code)
public static ALErrorCategory ClassifyAlStatusCode(ushort alStatusCode)
按 ETG.1020 把 AL Status Code 归类为 None / Transient / Configuration / Hardware / Unknown 五类.
返回值:
ALErrorCategory— 错误分类
相关结构:
public enum ALErrorCategory
{
None, // 无错误
Transient, // 临时错误 (可自动恢复)
Configuration, // 配置错误 (需重新配置)
Hardware, // 硬件错误 (需用户干预)
Unknown // 未知错误
}
示例:
ushort code = (ushort)slave.ErrorCode;
var cat = DarraEtherCAT.ClassifyAlStatusCode(code);
if (cat == ALErrorCategory.Transient)
master.Restart();
EsmTimeouts
public static class EsmTimeouts
{
public const int InitToPreOp = 3000;
public const int PreOpToSafeOp = 10000;
public const int SafeOpToOp = 3000;
public const int OpToSafeOp = 200;
public const int SafeOpToPreOp = 200;
public const int PreOpToInit = 200;
public const int ToBoot = 3000;
public const int BootToInit = 3000;
public static int GetTransitionTimeout(EcState current, EcState target);
}
ETG.1020 默认 ESM 状态转换超时常量 (毫秒). GetTransitionTimeout 按 (current, target) 匹配返回对应常量, 未匹配返回 3000.
示例:
int timeoutMs = EsmTimeouts.GetTransitionTimeout(EcState.PreOp, EcState.SafeOp);
// timeoutMs == 10000
ALErrorClassifier
public static class ALErrorClassifier
{
public static ALErrorCategory Classify(ushort alStatusCode);
public static ALErrorCategory Classify(EcALState alState);
}
ALErrorCategory 的纯 C# 静态实现 (与 DLL 版 ClassifyAlStatusCode 等价). 离线场景或不希望走 P/Invoke 时使用.
示例:
var cat = ALErrorClassifier.Classify(0x001B); // SM 看门狗超时
// cat == ALErrorCategory.Transient