4. 代码结构
如图 1 所示,EtherCAT 从站协议栈由三部分组成:
- PDI / 硬件抽象层
- 通用 EtherCAT 协议栈
- 用户应用程序

硬件访问层需提供的函数和宏定义在第 5 章 "硬件访问" 中。通用 EtherCAT 协议栈的行为在 ETG.1000 规范 [2] 中有详细描述。应用程序需提供的函数定义在第 6 章 "应用程序" 中。
图 2 展示了从站协议栈代码各层与源文件的关联关系:

可通过从站协议栈代码工具(第 12 章),根据应用程序的特定需求调整代码结构。
5. 硬件访问
从站协议栈代码可在多种平台和控制器架构上运行。本章介绍可用的硬件实现 / 设置,以及如何实现用户特定的硬件访问。
为支持多种硬件架构,SSC 包含多个设置以满足特定硬件需求。表 1 "硬件相关设置" 列出了已定义的硬件设置(位于 ecat_def.h 或 SSC 工具中)。
表 1:硬件相关设置
| 定义 | 描述 |
|---|---|
| EL9800_HW | 当从站代码在倍福自动化有限公司的 EL9800 EtherCAT 评估板上的 PIC 控制器上运行时的硬件访问配置,包括 PIC 初始化和通过 SPI 访问 ESC。若 SSC 需适配其他通过 SPI 访问 ESC 的 8 位或 16 位微控制器,也可使用此配置 |
| PIC24 | 激活针对 Microchip PCI24HJ128GP306 微控制器的配置,该微控制器自版本 4A 起搭载于 EL9800 EtherCAT 评估板。仅当定义 "EL9800_HW" 时,此设置才生效 |
| PIC18 | 激活针对 Microchip PIC18F452 微控制器的配置,该微控制器搭载于 EL9800 EtherCAT 评估板(版本 2)。仅当定义 "EL9800_HW" 时,此设置才生效 |
| MCI_HW | 通用 MCI 实现,适用于通过任何类型内存接口访问 ESC 的场景 |
| FC1100_HW | 倍福 FC1100 PCI EtherCAT 从站卡的专用硬件实现,适用于 Win32 操作系统 |
| CONTROLLER_16BIT | 当从站代码为 16 位微控制器编译时使用此设置 |
| CONTROLLER_32BIT | 当从站代码为 32 位微控制器编译时使用此设置 |
| ESC_16BIT_ACCESS | 若设置此选项,仅对 ESC 执行 16 位对齐访问 |
| ESC_32BIT_ACCESS | 若设置此选项,仅对 ESC 执行 32 位对齐访问 |
| MBX_16BIT_ACCESS | 若设置此选项,从站代码仅对邮箱数据执行 16 位对齐访问。若邮箱数据复制到本地微控制器内存且定义了 "CONTROLLER_16BIT",则应同时设置此定义 |
| BIG_ENDIAN_16BIT | 若微控制器始终以 16 位方式访问外部内存,且采用大端格式(高低字节切换由硬件完成),则需设置此定义 |
| BIG_ENDIAN_FORMAT | 若微控制器采用大端格式,则设置此选项 |
设置 "EL9800_HW""PIC24""PIC18""MCI_HW""FC1100_HW" 用于激活预定义的硬件访问实现。表 2 "推荐硬件配置" 列出了部分平台 / 微控制器及对应的推荐设置。使用 SSC 工具创建新项目时,部分配置可直接选择(见注释)。若未使用上述任何设置,则需向从站项目添加用户特定的硬件访问文件。
表 2:推荐硬件配置
| 平台 | EL9800_HW | PIC24 | PIC18 | MCI_HW | FC1100_HW | CONTROLLER_16BIT | CONTROLLER_32BIT | ESC_16BIT_ACCESS | ESC_32BIT_ACCESS | MBX_16BIT_ACCESS | BIG_ENDIAN_16BIT | BIG_ENDIAN_FORMAT | 说明 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Microchip PIC18F452(通用:8 位微控制器;SPI ESC 访问) | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 若使用 EL9800 EtherCAT 评估板上的 PIC18,协议栈可直接使用;否则可能需要适配硬件访问 |
| Microchip PIC24HJ128GP306(通用:16 位微控制器;SPI ESC 访问) | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 若使用 EL9800 EtherCAT 评估板上的 PIC24,协议栈可直接使用;否则可能需要适配硬件访问 |
| x86(操作系统:Windows) | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 若协议栈在 Win32 操作系统用户模式下运行,可直接使用;否则可能需要修改硬件访问。"FC1100_HW" 是基于 "MCI_HW" 的适配实现 |
| 德州仪器 Sitara AM335x | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 若要在 TI AM335x 芯片上使用 SSC,需将 TI SDK 中的硬件访问文件添加到项目中。可通过 SDK 提供的补丁文件、在 SSC 工具中选择 TI 配置或手动添加文件的方式完成 |
| Altera® NIOS®II(ESC 通过 Avalon 总线连接) | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | 0 | 0 | x:取决于 SOPC 构建器中的 NIOS® 配置。通常需适配以下内容:- 定义 "MAKE_PTR_TO_ESC" - 定时器 / PDI 中断和 Sync0 的 ISR(取决于支持的功能) - 实现定时器访问函数和宏。根据平台配置,可能还需要进一步修改 |
| Xilinx Microblaze™(ESC 通过 PLB 总线连接) | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | 0 | 0 | x:取决于 Microblaze™配置。通常需适配以下内容:- 定义 "MAKE_PTR_TO_ESC" - 定时器 / PDI 中断和 Sync0 的 ISR(取决于支持的功能) - 实现定时器访问函数和宏。根据平台配置,可能还需要进一步修改 |
| 瑞萨 - RIN32M3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 若要在瑞萨 RIN32M3 芯片上使用 SSC,需向项目添加芯片专用的硬件访问文件。在 SSC 工具中选择瑞萨 PIN32M3 配置时,文件会自动添加 |
硬件访问实现需支持的功能
- ESC 读写访问
- 定时器提供(至少 1ms 基准时钟周期)
- 每 1ms 调用一次定时器处理程序(仅当支持定时器中断处理,且 "ECAT_TIMER_INT" 设为 1 时需要)
- 调用中断特定函数(仅当支持同步时需要):
- PDI ISR(当 "AL_EVENT_SUPPORTED" 设为 1 时需要)
- SYNC0 ISR(当 "DC_SUPPORTED" 设为 1 时需要)
5.1 中断处理程序
以下函数由通用从站协议栈代码提供(定义在 ecatappl.h 中),需从硬件访问层调用:
| 函数原型 | 参数 | 返回值 | 描述 |
|---|---|---|---|
| void ECAT_CheckTimer (void) | 无 | 无 | 若支持定时器中断(ECAT_TIMER_INT = 1),需每 1ms 从定时器 ISR 中调用此函数;若不支持定时器中断,当 1ms 时间间隔到达时(基于提供的定时器),该函数会自动调用 |
| void PDI_Isr (void) | 无 | 无 | 需从 PDI ISR 中调用此函数。关于 PDI 专用引脚命名和中断生成逻辑,请参考 [6]。要支持 PDI 中断处理,还需将 "AL_EVENT_ENABLED" 设为 1 |
| void Sync0_Isr (void) | 无 | 无 | 需从 Sync0 ISR 中调用此函数。Sync0 中断由 ESC 的 DC 单元生成。默认情况下,不支持将 Sync0 信号映射到 PDI 中断。要支持 DC 同步,需将 "DC_SUPPORTED" 设为 1 |
| void Sync1_Isr (void) | 无 | 无 | 需从 Sync1 ISR 中调用此函数。Sync1 中断由 ESC 的 DC 单元生成。默认情况下,不支持将 Sync1 信号映射到 PDI 中断。要支持 DC 同步,需将 "DC_SUPPORTED" 设为 1 |
5.2 接口函数 / 宏
本章列出的函数和宏需由硬件访问层实现。
5.2.1 通用函数 / 宏
| 函数原型 | 参数 | 返回值 | 描述 |
|---|---|---|---|
| UINT16 HW_Init(void) | 无 | 0:初始化成功;>0:初始化过程中发生错误 | 初始化主机控制器、过程数据接口(PDI),并分配硬件访问所需的资源 |
| void HW_Release(void) | 无 | 无 | 释放已分配的资源 |
| UINT16 HW_GetALEventRegister(void) | 无 | 寄存器 0x220-0x221 的内容 | 获取 AL 事件寄存器的前两个字节(0x220-0x221) |
| UINT16 HW_GetALEventRegister_Isr(void) | 无 | 寄存器 0x220-0x221 的内容 | 若需要从中断服务程序中对 ESC 进行特殊访问,则需实现此函数;否则,该函数定义为 HW_GetALEventRegister。功能:获取 AL 事件寄存器的前两个字节(0x220-0x221) |
| void HW_ResetALEventMask(UINT16 intMask) | "intMask":中断掩码(禁用的中断设为 0) | 无 | 与 AL 事件掩码寄存器(0x0204 : 0x0205)执行逻辑与操作。仅当 "AL_EVENT_ENABLED" 设为 1 时,需要此函数 |
| void HW_SetALEventMask(UINT16 intMask) | "intMask":中断掩码(启用的中断设为 1) | 无 | 与 AL 事件掩码寄存器(0x0204 : 0x0205)执行逻辑或操作。仅当 "AL_EVENT_ENABLED" 设为 1 时,需要此函数 |
| void HW_SetLed(UINT8 RunLed,UINT8 ErrLed) | "RunLed":EtherCAT 运行 LED 状态;"ErrLed":EtherCAT 错误 LED 状态 | 无 | 更新 EtherCAT 运行 LED 和错误 LED(或 EtherCAT 状态 LED) |
| void HW_RestartTarget(void) | 无 | 无 | 重置硬件。仅当 "BOOTSTRAPMODE_SUPPORTED" 设为 1 时,需要此函数 |
| void HW_DisableSyncManChannel(UINT8 channel) | "channel":同步管理器通道 | 无 | 禁用选定的同步管理器通道,设置对应 0x807 寄存器的位 0 |
| void HW_EnableSyncManChannel (UINT8 channel) | "channel":同步管理器通道 | 无 | 启用选定的同步管理器通道,重置对应 0x807 寄存器的位 0 |
| TSYNCMAN HW_GetSyncMan(UINT8 channel) | "channel":同步管理器通道 | TSYNCMAN 结构(大小固定为 8 字节,内容取决于支持的 ESC 访问方式) | 获取指定通道的同步管理器寄存器内容,从 0x800 + 8*channel 开始读取 8 字节 |
| UINT32 HW_GetTimer(void) | 无 | 当前定时器值 | 读取硬件定时器的当前寄存器值;若没有硬件定时器,返回多媒体定时器的计数器值。定时器滴答值(每毫秒增量)定义在 "ECAT_TIMER_INC_P_MS" 中。当不支持定时器中断("ECAT_TIMER_INT" = 0)且需要计算总线周期时,需要此函数 |
| void HW_ClearTimer(void) | 无 | 无 | 清除硬件定时器值 |
| UINT16 HW_EepromReload (void) | 无 | 0:EEPROM 加载正确;<>0:EEPROM 重新加载过程中出错 | 当主站触发 EEPROM 重新加载请求时,调用此函数。仅当支持 EEPROM 仿真时,需要此函数 |
5.2.2 读取访问
| 函数原型 | 参数 | 返回值 | 描述 |
|---|---|---|---|
| void HW_EscRead(MEM_ADDR *pData, UINT16 Address, UINT16 Len ) | "pData":指向本地目标缓冲区的指针(指针类型取决于主机控制器架构,在 ecat_def.h 或 SSC 工具中指定);"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用与 8 位 / 16 位或 32 位 ESC 访问对应的有效地址);"Len":访问大小(字节数) | 无 | 从 EtherCAT 从站控制器读取数据,用于访问 ESC 寄存器和 DPRAM 区域 |
| void HW_EscReadIsr(MEM_ADDR *pData, UINT16 Address, UINT16 Len ) | "pData":指向本地目标缓冲区的指针(指针类型取决于主机控制器架构,在 ecat_def.h 或 SSC 工具中指定);"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用与 8 位 / 16 位或 32 位 ESC 访问对应的有效地址);"Len":访问大小(字节数) | 无 | 若需要从中断服务程序中对 ESC 进行特殊访问,则需实现此函数;否则,该函数定义为 "HW_EscRead"。功能:从 EtherCAT 从站控制器读取数据,用于访问 ESC 寄存器和 DPRAM 区域 |
| void HW_EscReadDWord(UINT32 *DWordValue, UINT16 Address) | "DWordValue":存储寄存器值的本地 32 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用有效 32 位地址) | 无 | 从 EtherCAT 从站控制器的指定地址读取一个双字(32 位)数据 |
| void HW_EscReadDWordIsr(UINT32 *DWordValue, UINT16 Address) | "DWordValue":存储寄存器值的本地 32 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用有效 32 位地址) | 无 | 若需要从中断服务程序中对 ESC 进行特殊访问,则需实现此函数;否则,该函数定义为 "HW_EscReadDWord"。功能:从 EtherCAT 从站控制器的指定地址读取一个双字(32 位)数据 |
| void HW_EscReadWord(UINT16 *WordValue, UINT16 Address) | "WordValue":存储寄存器值的本地 16 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用有效 16 位地址) | 无 | 从 EtherCAT 从站控制器的指定地址读取一个字(16 位)数据。仅当 "ESC_32BIT_ACCESS" 未设置时,需要此函数 |
| void HW_EscReadWordIsr(UINT16 *WordValue, UINT16 Address) | "WordValue":存储寄存器值的本地 16 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用有效 16 位地址) | 无 | 若需要从中断服务程序中对 ESC 进行特殊访问,则需实现此函数;否则,该函数定义为 "HW_EscReadWord"。功能:从 EtherCAT 从站控制器的指定地址读取一个字(16 位)数据。仅当 "ESC_32BIT_ACCESS" 未设置时,需要此函数 |
| void HW_EscReadByte(UINT8 *ByteValue, UINT16 Address) | "ByteValue":存储寄存器值的本地 8 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量) | 无 | 从 EtherCAT 从站控制器读取一个字节(8 位)数据。仅当 "ESC_16BIT_ACCESS" 和 "ESC_32BIT_ACCESS" 均未设置时,需要此函数 |
| void HW_EscReadByteIsr(UINT8 *ByteValue, UINT16 Address) | "ByteValue":存储寄存器值的本地 8 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量) | 无 | 若需要从中断服务程序中对 ESC 进行特殊访问,则需实现此函数;否则,该函数定义为 "HW_EscReadByte"。功能:从 EtherCAT 从站控制器读取一个字节(8 位)数据。仅当 "ESC_16BIT_ACCESS" 和 "ESC_32BIT_ACCESS" 均未设置时,需要此函数 |
| void HW_EscReadMbxMem(MEM_ADDR *pData, UINT16 Address, UINT16 Len ) | "pData":指向本地目标邮箱缓冲区的指针(指针类型取决于主机控制器架构,在 ecat_def.h 或 SSC 工具中指定);"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用与 8 位 / 16 位或 32 位 ESC 访问对应的有效地址);"Len":访问大小(字节数) | 无 | 从 ESC 读取数据并复制到从站邮箱内存。若本地邮箱内存也位于应用程序内存中,则此函数与 "HW_EscRead" 功能相同 |
5.2.3 写入访问
| 函数原型 | 参数 | 返回值 | 描述 |
|---|---|---|---|
| void HW_EscWrite(MEM_ADDR *pData, UINT16 Address, UINT16 Len ) | "pData":指向本地源缓冲区的指针(指针类型取决于主机控制器架构,在 ecat_def.h 或 SSC 工具中指定);"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用与 8 位 / 16 位或 32 位 ESC 访问对应的有效地址);"Len":访问大小(字节数) | 无 | 向 EtherCAT 从站控制器写入数据,用于访问 ESC 寄存器和 DPRAM 区域 |
| void HW_EscWriteIsr(MEM_ADDR *pData, UINT16 Address, UINT16 Len ) | "pData":指向本地源缓冲区的指针(指针类型取决于主机控制器架构,在 ecat_def.h 或 SSC 工具中指定);"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用与 8 位 / 16 位或 32 位 ESC 访问对应的有效地址);"Len":访问大小(字节数) | 无 | 若需要从中断服务程序中对 ESC 进行特殊访问,则需实现此函数;否则,该函数定义为 "HW_EscWrite"。功能:向 EtherCAT 从站控制器写入数据,用于访问 ESC 寄存器和 DPRAM 区域 |
| void HW_EscWriteDWord(UINT32 DWordValue, UINT16 Address) | "DWordValue":包含要写入 ESC 内存区域数据的本地 32 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用有效 32 位地址) | 无 | 向 EtherCAT 从站控制器的指定地址写入一个双字(32 位)数据 |
| void HW_EscWriteDWordIsr(UINT32 DWordValue, UINT16 Address) | "DWordValue":包含要写入 ESC 内存区域数据的本地 32 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用有效 32 位地址) | 无 | 若需要从中断服务程序中对 ESC 进行特殊访问,则需实现此函数;否则,该函数定义为 "HW_EscWriteDWord"。功能:向 EtherCAT 从站控制器的指定地址写入一个双字(32 位)数据 |
| void HW_EscWriteWord(UINT16 WordValue, UINT16 Address) | "WordValue":包含要写入 ESC 内存区域数据的本地 16 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用有效 16 位地址) | 无 | 向 EtherCAT 从站控制器的指定地址写入一个字(16 位)数据。仅当 "ESC_32BIT_ACCESS" 未设置时,需要此函数 |
| void HW_EscWriteWordIsr(UINT16 WordValue, UINT16 Address) | "WordValue":包含要写入 ESC 内存区域数据的本地 16 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用有效 16 位地址) | 无 | 若需要从中断服务程序中对 ESC 进行特殊访问,则需实现此函数;否则,该函数定义为 "HW_EscWriteWord"。功能:向 EtherCAT 从站控制器的指定地址写入一个字(16 位)数据。仅当 "ESC_32BIT_ACCESS" 未设置时,需要此函数 |
| void HW_EscWriteByte (UINT8 ByteValue, UINT16 Address) | "ByteValue":包含要写入 ESC 内存区域数据的本地 8 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量) | 无 | 向 EtherCAT 从站控制器写入一个字节(8 位)数据。仅当 "ESC_16BIT_ACCESS" 和 "ESC_32BIT_ACCESS" 均禁用时,定义此函数 |
| void HW_EscWriteByteIsr(UINT8 ByteValue, UINT16 Address) | "ByteValue":包含要写入 ESC 内存区域数据的本地 8 位变量;"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量) | 无 | 若需要从中断服务程序中对 ESC 进行特殊访问,则需实现此函数;否则,该函数定义为 "HW_EscWriteByte"。功能:向 EtherCAT 从站控制器写入一个字节(8 位)数据。仅当 "ESC_16BIT_ACCESS" 和 "ESC_32BIT_ACCESS" 均禁用时,定义此函数 |
| void HW_Esc_Write_MbxMem(MEM_ADDR *pData, UINT16 Address, UINT16 Len ) | "pData":指向本地源邮箱缓冲区的指针(指针类型取决于主机控制器架构,在 ecat_def.h 或 SSC 工具中指定);"Address":EtherCAT 从站控制器地址(指定 ESC 内存区域内的字节偏移量,仅使用与 8 位 / 16 位或 32 位 ESC 访问对应的有效地址);"Len":访问大小(字节数) | 无 | 将从站邮箱内存中的数据写入 ESC 内存。若本地邮箱内存也位于应用程序内存中,则此函数与 "HW_EscWrite" 功能相同 |
来源:AN_ET9300.pdf
用作个人学习和分享,侵删