简介:这份文档面向嵌入式开发工程师与工业以太网学习者,围绕STM32F103与LAN9252构建EtherCAT从站这一典型方案展开,重点解决从站开发中硬件选型、协议栈移植与配置的入门难题。内容涵盖LAN9252四种工作模式的对比与SPI模式选择依据、XML设备描述文件与SSC工具的使用、协议栈HW_Init/MainInit/MainLoop骨架解析,以及SPI接口、1ms定时器和IRQ、SYNC0/SYNC1外部中断的配置要点,并给出中断回调处理示例。资源包共1个docx文件,约1.75MB,以图文文档形式系统梳理开发流程与移植注意事项。目前已有2921人学习,适合具备一定嵌入式基础、希望快速上手EtherCAT从站设计的读者参考,可帮助理清协议栈结构、少走配置弯路。
1. 从一块学习板到 64 入 64 出从站:这套方案到底解决什么问题
接手这个需求的时候,手上只有一台倍福 CX9020 主站和一句“做 64 入 64 出的从站”。主站跑的是 Windows CE 加 TwinCAT2.0,ARM 架构,网卡是专用的;从站这边要自己选芯片、画板子、写协议栈、配 XML,最后还得让 PLC 能扫到、能读写。EtherCAT 从站开发的门槛不在写代码,而在“协议栈是个黑匣子”——几万行代码几乎读不动,能动的只有几个入口函数和几个中断。这套方案要解决的就是把黑匣子外围的接口一个个接对:STM32F103 负责应用逻辑,LAN9252 负责 PHY、网络交换和 SPI 从机,中间靠四线 SPI 和三个外部中断串起来。适合正在做工业通信毕设、课设,或者要交付一台自研从站样机的读者,照着这套结构走,能少踩很多“上电就连不上”的坑。
2. 总体方案设计:主站、从站与 LAN9252 的职责切分
2.1 主站侧的能力边界先摸清
主站是一台 CX9020,装 Windows CE 和 TwinCAT2.0,这意味着两件事:第一,它只认 TwinCAT2 时代的 ESI 文件格式,XML 里某些新版本节点写了也白写;第二,它的网卡是倍福自家实时网卡,扫描从站时对 EEPROM 里的 ConfigData 校验比较严格,ConfigData 不对,设备能出现在扫描列表里但进不了 OP 状态。所以方案的第一步不是画板子,而是确认主站能接受什么。通常的做法是先在 TwinCAT 的 Io/EtherCAT 目录下放一份已知能用的 ESI,扫一遍现成设备,确认主站链路本身没问题,再动自己的 XML。这一步省掉,后面所有“连不上”都会怀疑到自己头上,排查成本翻倍。
2.2 从站三块职责:PHY、交换、SPI 从机
LAN9252 在这套体系里干三件事,缺一不可。第一是 PHY,所有 RJ45 上的差分信号、链路建立、自协商都由它完成,STM32 完全不碰以太网物理层。第二是网络交换,EtherCAT 要求从站具备一拖一能力,不能终结总线,LAN9252 的 2 端口/3 端口模式在内部做转发,一进一出。第三是数据解析加 SPI 从机,MCU 作为 SPI 主模式去读写 LAN9252 内部寄存器,过程数据、邮箱、状态字全在这条 SPI 上跑。把这三块职责想清楚,原理图阶段就不会犯“把 RJ45 直接接到 MCU”这种方向性错误。
2.3 工作模式选型:为什么是 SPI 而不是 HBI
LAN9252 有四种模式:数字 I/O 模式(8 入 8 出)、SPI 串口模式、并行 HBI 模式、扩展模式。项目要 64 入 64 出,数字 I/O 模式点位不够直接出局;HBI 并行模式速度快,但要占用 16 根数据线加一堆控制线,STM32F103 的引脚本来就紧张,PCB 布线也复杂;扩展模式是给需要双 RJ45 加额外 PHY 的场景,本项目用不上。SPI 四线(SCK、MISO、MOSI、CS)就能跑,标准模式时钟最高 30MHz,高速 SPI 模式可到 80MHz,对 64+64 字节的周期数据绰绰有余。选 SPI 的代价是每次读写都要走命令加地址加数据的时序,协议栈里对时序要求严,这一点在第 5 章的适配里会展开。
2.4 整体数据流与开发流程
数据流是这样的:主站发周期帧 → LAN9252 收到后解析出过程数据放进内部缓冲 → 拉 IRQ 中断通知 STM32 → STM32 在 PDI_Isr 里通过 SPI 把输入数据读走、把输出数据写回 → LAN9252 在下一个周期把输出数据发回主站。整个开发流程按依赖顺序排:先拿学习板跑通官方例程,理解协议栈骨架;再用 SSC 生成 XML 和对象字典代码;然后按项目需求改 XML 的 IO 点位和 ConfigData;接着画自己的原理图和 PCB;最后把协议栈移植到自己的 MCU 上,在 TwinCAT 里组态调试。顺序不能乱,尤其是 XML 没定稿就画板子,后面改点位要重新烧 EEPROM,返工成本很高。
3. XML 与 EEPROM 配置:让主站认得这块从站
3.1 SSC 生成 XML 的正确姿势
SSC 是 EtherCAT 协会给会员的从站协议栈代码工具,新建项目时不要用默认模板,选 Custom 后下拉出 EL9800 | 8Bit Digital I/O, 16Bit Analog Input 这个模板,它对应的是 EL9800 评估板的 SPI 加 PIC24 配置,跟本项目 STM32 加 LAN9252 的 SPI 架构最接近。选完模板后依次点 Tool → Application → Create New,保存工程时会弹出一个 Excel,这份 Excel 就是 IO 点位的定义表。把 //0x6nnx 段配成 64 个输入位、//0x7nnx 段配成 64 个输出位,用 Excel 的批量拖拽填,最后把 Maximum number of modules 改成 3。保存 Excel 后 SSC 会自动导入,再点 Project → Create new Slave Files 生成协议栈和 XML。这一步的关键认知是:XML 里几兆的内容绝大部分是 SSC 根据 Excel 自动生成的字典和 Entry,手工写几乎不可能,所以 Excel 填错一位,后面全错。
3.2 XML 里必须手改的几处
SSC 生成的 XML 是以 ET1100 为蓝本,直接给 LAN9252 用会连不上。必须改的地方集中在 Descriptions → Devices → Device 节点下。ProductCode 和 RevisionNo 决定 XML 的唯一性,两份 XML 这两个字段一样,TwinCAT 只认其中一个,所以产品迭代时版本号要跟着升。Physics 节点填 YY 表示两个 RJ45 一进一出,不要填成 K(那是倍福 EBUS 专用口)。最关键是 ConfigData 这 14 个字节,SSC 默认给的是 ET1100 的 050E03440A0000000000,按 LAN9252 手册 AN1907 的迁移说明改成 800E00CC8813F0000000800000。第一个字节 80 对应 0140h 寄存器(Process Data Interface),配成 80h 就是 SPI 模式,跟项目架构对上。后面几个字节暂时不理解就保持默认,不要凭感觉改。
<!-- LAN9252 的 ConfigData,第一个字节 0x80 表示 SPI 模式 --> <ConfigData>800E00CC8813F0000000800000</ConfigData> <!-- EEPROM 逻辑容量,物理芯片用 24FC512 留足余量 --> <ByteSize>2048</ByteSize>上面这段是 XML 里 EEPROM 节点的核心内容。ByteSize 写 2048 是逻辑容量,物理上挂的是 24FC512(512Kbit),留余量是为了后续 IO 点位增加时不用换芯片。EEPROM 芯片选型有个血泪经验:尽量用 ATMEL 的 24FC512,换其他家的同容量芯片,EtherCAT 连接偶发失败的概率明显上升,时序和上电初始化行为有差异,这种问题查起来非常玄学。
3.3 字典与 IO 点位的对应关系
XML 里 Profile 节点下有 DataType 和 Objects 两个子节点,前者像 C 语言的 typedef,后者像变量定义。比如 Objects 里有个 index 为 #x1008 的 Device name,type 是 STRING(10),就要去 DataType 里找 STRING(10) 的定义,BitSize 是 80 bit,也就是 uchar[10]。这个字符串的内容就是前面硬件信息里定义的 Device Name,数一数正好 10 字节。这种对应关系理不顺,EtherCAT 就建不了连接。IO 点位在 Device 节点下的四个 Sm 通道里,Inputs 和 Outputs 分别指向 RxPdo 和 TxPdo,每个 Entry 就是 Excel 里定义的一个点位,SSC 生成了 64+64 个 Entry。Sm 通道的 size 要 16 位对齐,Entry 的 bitlen 和 subindex 属性也有讲究,这部分内容脱胎于 CANopen 的对象字典,想深究可以去翻 CANopen 协议。
4. STM32 外设配置:SPI、定时器与三个中断
4.1 CubeMX 里配什么、不配什么
用 STM32CubeMX 新建 STM32F103ZExx 工程,需要配的外设就四类:SPI1 四线标准模式、一个 1ms 定时器、三个外部中断(IRQ、SYNC0、SYNC1)。SPI 不需要开中断,因为 SPI 通信是读的同时写、写的同时读,读写不分离,配中断没有意义。三个外部中断在 CubeMX 里可以先配成初始 enable,这样生成的代码结构完整,但生成后要到 Keil 里把初始化函数最后一行使能语句注释掉。原因很直接:什么时候开中断、什么时候关中断必须由协议栈决定,一上电就使能外部中断,协议栈还没初始化完就进中断,基本连不上。定时器中断同理,CubeMX 里配好,代码里注释掉使能,留接口给协议栈调用。
/* CubeMX 生成的 MX_GPIO_Init 末尾,把这三行注释掉 */ /* HAL_NVIC_EnableIRQ(LAN9252_IRQ_EXTI_IRQn); */ /* HAL_NVIC_EnableIRQ(LAN9252_SYNC0_EXTI_IRQn); */ /* HAL_NVIC_EnableIRQ(LAN9252_SYNC1_EXTI_IRQn); */ /* 定时器中断也使能入口留给协议栈 */ /* HAL_TIM_Base_Start_IT(&htim2); */这段注释掉的是“上电即开”的默认行为,不是永久禁用。协议栈在 HW_Init 和 MainInit 阶段会通过它自己的接口去调用使能函数,时机由它掌握。NVIC 优先级分配上,一个可行的方案是 2 bit 抢先、2 bit 响应:ECAT_CheckTimer 配 1 抢先 0 响应,PDI_Isr 配 1 抢先 0 响应,Sync0_Isr 和 Sync1_Isr 配 2 抢先 0 响应。同步中断优先级低一点,避免打断主中断的数据处理。
4.2 中断服务函数的对接
协议栈暴露给 MCU 的入口就四个:PDI_Isr、Sync0_Isr、Sync1_Isr、ECAT_CheckTimer。CubeMX 生成的 HAL_GPIO_EXTI_Callback 里按引脚分发,SYNC0 和 SYNC1 处理前后要关、开 ESC 中断,防止同步中断打断正在进行的 SPI 事务。
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == LAN9252_IRQ_Pin) { PDI_Isr(); /* 主中断:过程数据收发 */ return; } if (GPIO_Pin == LAN9252_SYC0_Pin) { DISABLE_ESC_INT(); /* 同步中断期间屏蔽 ESC 中断 */ Sync0_Isr(); ENABLE_ESC_INT(); return; } if (GPIO_Pin == LAN9252_SYC1_Pin) { DISABLE_ESC_INT(); Sync1_Isr(); ENABLE_ESC_INT(); return; } }IRQ 是必须实现的,SYNC0 和 SYNC1 是分布式时钟同步用的,项目不用分布式时钟可以不接,但引脚和中断入口建议预留,后面要加 DC 不用改板子。DISABLE_ESC_INT 和 ENABLE_ESC_INT 是协议栈提供的宏,操作的是 LAN9252 内部的中断屏蔽寄存器,不是 STM32 的 NVIC,别搞混。
4.3 协议栈骨架:三个函数加一个死循环
协议栈几万行读不动,但骨架就四行:HW_Init()、MainInit()、while(1) 里的 MainLoop()。HW_Init 做硬件初始化,包括 SPI 引脚、LAN9252 复位、EEPROM 加载;MainInit 初始化协议栈内部状态机;MainLoop 是主循环,处理邮箱、状态机迁移、看门狗。移植的本质不是改协议栈,而是把协议栈期望的底层函数名实现出来,让它调用你的 SPI 读写、你的中断使能。所以读代码的正确姿势是从 main() 进,顺着 HW_Init 往下看它调了哪些底层接口,把这些接口在 STM32 上实现,而不是试图理解整个协议栈。
5. 避坑与排查:上电连不上时先查这五处
5.1 现象:设备能扫到但进不了 OP 状态
原因多半在 ConfigData。SSC 默认生成的是 ET1100 的 14 字节,没改成 LAN9252 的 800E00CC8813F0000000800000,或者第一个字节不是 80(SPI 模式)。主站扫描时读 EEPROM 发现 PHY 配置和实际工作模式对不上,状态机卡在 PREOP 之前。解决办法是重新确认 XML 的 ConfigData 节点,改完重新在 TwinCAT 里烧录 EEPROM,烧录后断电重启再扫描。
5.2 现象:一上电就进中断,然后死机或连不上
原因是 CubeMX 生成的代码里外部中断和定时器中断默认使能了,协议栈还没初始化完就进 PDI_Isr,里面访问的全局变量全是未初始化状态。解决就是把 MX_GPIO_Init 和定时器初始化末尾的 HAL_NVIC_EnableIRQ、HAL_TIM_Base_Start_IT 注释掉,让协议栈在 HW_Init 完成后自己调使能接口。这个坑几乎每个新手都会踩一次,现象很吓人,原因很简单。
5.3 现象:SPI 读写偶发数据错位
先查 SPI 时钟极性相位。LAN9252 的 SPI 模式 0(CPOL=0,CPHA=0)是常用配置,但不同批次或不同布线长度下,30MHz 标准模式可能不稳,降到 15MHz 先验证功能,功能通了再往上提。再查 CS 片选时序,LAN9252 要求 CS 拉低到第一个 SCK 沿之间有建立时间,CubeMX 默认配置一般够,但如果用软件控制 CS,中间插了其他操作就会出问题。最后查 PCB 上 SPI 走线,四根线尽量等长、远离 RJ45 差分对。
5.4 现象:EEPROM 烧录成功但重启后配置丢失
检查 EEPROM 芯片型号和 ByteSize 是否匹配。XML 里 ByteSize 写 2048,物理芯片是 24FC512,逻辑容量小于物理容量没问题;反过来物理芯片容量不够,烧录会截断。另外确认 EEPROM 的 I2C 地址和 LAN9252 的 EEPROM 接口配置一致,不同封装地址引脚接法不同。换非 ATMEL 芯片出现的偶发丢失,优先怀疑上电时序和写保护引脚处理。
5.5 现象:TwinCAT 里两个 XML 只认一个
ProductCode 和 RevisionNo 重复了。TwinCAT 用这两个字段做唯一性判断,两份 XML 放同一目录下只加载其中一个。给每个硬件版本分配独立的 RevisionNo,迭代时递增,不要图省事复制粘贴。
6. 验收与答辩:怎么证明这套从站真的跑通了
验收分三层,从底往上逐层过,哪层不过就停在哪层查,不要跳。第一层是电气与链路:上电后 LAN9252 的 LINK 灯亮,两个 RJ45 口一进一出能级联,用主站扫描能看到设备出现在列表中,状态至少到 PREOP。第二层是配置与通信:XML 烧录进 EEPROM 后断电重启,设备能进 SAFEOP 再到 OP,TwinCAT 里能看到 64 入 64 出的过程数据变量,输入点位随按键变化、输出点位能点亮 LED。第三层是周期与稳定性:让主站跑 1ms 周期,连续运行 30 分钟以上不掉线,看门狗不触发,用 TwinCAT 的在线监控看过程数据刷新无跳变。
答辩时最容易被问的三个问题,提前准备好答案。一是“为什么选 SPI 不选 HBI”,答引脚资源和布线复杂度,加上 64+64 字节的数据量 SPI 带宽足够。二是“ConfigData 那 14 个字节什么意思”,答第一个字节 80 对应 0140h 寄存器配成 SPI 模式,其余字节按 LAN9252 手册默认,不逐字节展开也行,但要能指出查手册的章节。三是“中断为什么不能上电就开”,答协议栈初始化顺序,中断里访问的全局状态未就绪,由协议栈控制使能时机是设计约束不是偷懒。
| 验收层级 | 检查项 | 通过标准 |
|---|---|---|
| 链路层 | LINK 灯、级联、扫描 | 设备出现在扫描列表,到 PREOP |
| 配置层 | EEPROM 烧录、状态机 | 断电重启后能进 OP |
| 应用层 | 64 入 64 出读写 | 输入随按键变,输出能驱动 LED |
| 稳定性 | 1ms 周期连续运行 | 30 分钟不掉线,看门狗不触发 |
我自己的习惯是每次改完 XML 或 ConfigData,都强制走一遍“烧录 → 断电 → 重启 → 扫描 → 进 OP”的完整流程,不在线热改,因为 EtherCAT 的 EEPROM 配置是上电加载的,热改看到的正常状态可能是假象。这个习惯是被一次“在线改完看着正常、交付后客户一断电就起不来”教出来的。希望帮到你。
本文还有配套的精品资源,点击获取