EtherCAT 状态机
EtherCAT的状态是由一个称为EtherCAT状态机(ESM: EtherCAT State Machine)来控制的。根据EtherCAT的状态,EtherCAT从站可以访问和执行不同的功能。EtherCAT 主站必须向每个状态下的设备发送特定命令,特别是在从站启动期间。
1 EtherCAT状态机:
- Init
- Pre-Operational: PreOp
- Safe-Operational: SafeOp
- Operational: OP
- Boot
1)Init :
初始化状态定义了主站与从站在应用层的初始通信关系。此时主站和从站应用层无法直接通信,主站使用初始化状态来初始化从站控制器的配置寄存器。如果从站支持邮箱通信,则主站使用初始化状态来配置邮箱通信。
2)Pre-Operational
PreOp状态下,可以使用邮箱通信,但还无法使用过程数据通信。EtherCAT 主站初始化用于过程数据的同步管理器通道(来自同步管理器通道 2)、FMMU 通道,以及(如果从站支持可配置映射)PDO 映射或同步管理器 PDO 分配。在此状态下,过程数据传输的设置以及可能与默认设置不同的终端特定参数也会被传输。
3) Safe-Operational
在 Pre-Op 和Safe-Op之间的转换期间,EtherCAT 从站会检查用于过程数据通信的同步管理器通道是否正确,如果需要,还会检查分布式时钟设置是否正确。在确认状态更改之前,EtherCAT 从站会将当前输入数据复制到 EtherCAT 从站控制器 (ESC) 的相关 DPRAM 区域中。
4) Operational
运行状态,从站程序读取输入数据,主站应用程序发出输出数据,从站设备产生输出信号。此时仍可以使用邮箱通信。
5)Boot
引导状态,在 Boot 状态下,可以更新从站的固件。Boot状态仅可以切换到 Init 状态。邮箱通信通过 File Access Over EtherCAT(FoE) 实现。
2 EtherCAT状态机初始化流程
状态及状态转换 | 主要操作 |
---|---|
Init | 初始状态,应用层无通信,主站只能读写ESC寄存器 |
Init > Pre-Op | 主站配置从站地址寄存器: - 如果支持邮箱通信,则配置邮箱通道参数 - 如果支持分布时钟,则配置分布时钟参数 主站写状态控制寄存器,请求Pre-Op状态切换 |
Pre-Op | 此时使用应用层的邮箱通信,如前述 |
Pre-Op > Safe-Op | 主站使用邮箱初始化过程数据映射 主站配置过程数据通信使用的SM通道 配置FMMU 主站写状态控制寄存器,请求Safe-Op状态切换 |
Safe-Op | 应用层支持邮箱数据通信 有过程数据通信,但只允许读输入数据,不产生输出信号 |
Safe-Op > Op | 主站发送有效的输出数据 主站写状态寄存器,请求Op状态切换 |
Op | 输入输出有效 仍可以使用邮箱通信 |
cpp
// -----------------------------------------------------------------------
// 主站执行状态机控制 Init -> Pre-OP -> Safe-Op -> Op
// int m_nStatus; 当前状态
// int m_nRequire; 请求状态
// 代码来源:《工业以太网现场总线------EtherCAT驱动程序设计及应用》
// 代码采用了较早的C版本,仅需要看懂状态机的编写逻辑,代码不可独立运行
// -----------------------------------------------------------------------
void CEcSimMaster::StateMachine()
{
if (m_nRequire > m_nStatus) // 状态上升
{
switch(m_nStatus) // 从当前状态开始执行
{
case 10: // 当前为Init状态
WriteAlControl(1); // 请求Init 状态
Delay(DELAYTIME); // 延时
WriteSM(0); // 配置从站SM0通道
Delay(DELAYTIME); // 延时
WriteSM(1); // 配置从站SM1通道
Delay(DELAYTIME); // 延时
WriteDlAddr(); // 为从站配置站点地址
Delay(DELAYTIME); // 延时
WriteAlControl(2); // 请求Pre-Op状态
m_nStatus = 11; // 主站程序进入中间状态
brake;
case 11:
ReadAlState(); // 读取从站状态
m_nStatus = 12;
break;
case 12:
if ((m_nReadStatus & 0x000f) == 2)
{
// 检查从站是否进入Pre-OP状态
m_nStatus = 20; // 如进入,则主站程序进入PreOP状态
}
else
{
m_nStatus = 11; // 如未进入,则主站程序进入中间状态
}
break;
case 20: // 当前状态为Pre-Op状态
WriteSM(2); // 配置从站SM2通道
Delay(DELAYTIME); // 延时
WriteSM(3); // 配置从站SM3通道
Delay(DELAYTIME); // 延时
WriteFmmu(0); // 配置从站FMMU0通道
Delay(DELAYTIME); // 延时
WriteFmmu(1); // 配置从站FMMU1通道
Delay(DELAYTIME); // 延时
WriteAlControl(4); // 请求Safe-Op状态
m_nStatus = 21; // 主站驱动程序进入等待状态
break;
case 21:
ReadAlState(); // 读从站状态
m_nStatus = 22;
break;
case 22:
if ((m_nReadStatus & 0x000f) == 4)
{
// 检查从站是否进入Safe-Op状态
m_nStatus = 40; // 如进入,则主站程序进入Safe-Op 状态
}
else
{
m_nStatus = 21; // 如为进入则退回上一状态继续等待
}
break;
case 40: // Safe-Op 状态
WriteAlControl(8); // 请求Op状态
m_nStatus = 41; // 主站驱动程序进入等待状态
break;
case 41:
ReadAlState(); // 读取从站状态
m_nStatus = 42;
break;
case 42:
if ((m_nReadStatus & 0x000f) == 8)
{
// 检查从站是否进入Op状态
m_nStatus = 80; // 如进入,则主站程序进入Op状态
}
else
{
m_nStatus = 41; // 如未进入,则退回上一状态继续等待
}
break;
}
}
else if (m_nRequire < m_nStatus) // 状态下降
{
WriteAlControl(m_nRequire/10); // 请求从站进入所请求的状态
m_nStatus = m_nRequire;
}
}