EtherCAT 状态机 (ESM)
新手知识
状态机听起来复杂,其实核心只有一句话:OP = 完全启动。只有到达 OP 状态,主站和从站之间才能正常收发数据。前面的 INIT → PREOP → SAFEOP 是逐步准备的过程,SDK 会自动完成。
状态机概述
每个 EtherCAT 从站都有状态机,控制其运行状态:

各状态说明
| 状态 | 英文 | 值 | 功能 |
|---|---|---|---|
| INIT | Init | 0x01 | 仅寄存器访问,无通信 |
| PREOP | Pre-Operational | 0x02 | Mailbox 通信可用,可配置 |
| SAFEOP | Safe-Operational | 0x04 | 输入有效,输出为安全值 |
| OP | Operational | 0x08 | 完全启动,正常数据交换 |
| BOOT | Bootstrap | 0x03 | 特殊模式,用于固件更新 |
状态详解与转换
INIT 状态
功能:
- 主站可读写 ESC 寄存器(端口状态、SII 信息等)
- 可识别从站身份(厂商 ID、产品代码)
- 应用层无通信
转换到 PREOP:
- 主站配置 DL 寄存器和配置地址(0x0010)
- 配置邮箱 SyncManager(SM0/SM1)
- 若使用 DC,同步系统时间到参考时钟
PREOP 状态
功能:
- 邮箱通信可用,可通过 SDO 读写参数
- 配置过程数据映射
- 无过程数据通信
转换到 SAFEOP:
- 下载启动命令和过程数据配置
- 配置过程数据 SyncManager(SM2 输出/SM3 输入)
- 配置 FMMU 通道
- 配置 DC 参数(周期、启动时间等)
- 主站开始发送过程数据帧
- 从站开始更新输入数据
SAFEOP 状态
功能:
- 邮箱通信和过程数据通信都运行
- 从站提供有效输入数据
- 输出保持安全值(如 0V,而非 24V)
转换到 OP:
- 若使用 DC,从站检查 DC 设置并锁定 PLL
- 监控输出数据是否在 DC Sync 事件前到达
- 主站开始发送有效输出值
- 从站确认 OP 后,将输出设置为接收值
OP 状态
功能:
- 输入和输出都有效
- 与 DC 精确同步(若使用)
- 邮箱通信可用
- 正常周期性数据交换
错误处理:
- 若 OP 状态发生错误,从站自动回退到较低状态
- 设置错误标志并提供 AL 状态码
- 主站可读取错误码进行诊断
状态转换流程
状态转换代码示例
方法一:SetState 直接切换
// 逐步切换到 OP 状态
// 库完全内置逐级切换功能, 自动配置功能, 可以自由切换状态机
master.SetState(EcState.Init);
master.SetState(EcState.PreOp);
master.SetState(EcState.SafeOp);
master.SetState(EcState.OP);
// 检查当前状态 (State 为只读属性, 切换状态一律用 SetState)
Console.WriteLine($"当前状态: {master.State}");
方法二:带错误信息的 SetState 重载
// SetState(state, out error) 返回 bool, 错误信息经 out 参数返回
if (!master.SetState(EcState.PreOp, out string message))
{
Console.WriteLine($"状态切换失败: {message}");
return;
}
// 继续切换到 OP
master.SetState(EcState.OP);
// 异步场景可用 SetStateAsync(EcState), 返回 Task<bool>
错误检测与恢复
// 实际操作中建议使用内置事件处理降级事件
// 检查状态
if (master.State != EcState.OP)
{
Console.WriteLine($"状态异常: {master.State}");
// 尝试重新启动
try
{
if (!master.SetState(EcState.PreOp, out string message))
{
Console.WriteLine($"状态恢复失败: {message}");
return;
}
Console.WriteLine("状态恢复成功");
}
catch (Exception ex)
{
Console.WriteLine($"恢复失败: {ex.Message}");
}
}