用STM32+LAN9252, 生成一个etherCAT 从机系统,实现数据采集功能

一、方案整体设计思路

要实现基于 STM32+LAN9252 的 EtherCAT 从机数据采集系统,核心逻辑是:

  1. 硬件层:STM32 作为主控,负责数据采集(模拟量 / 数字量)、EtherCAT 协议解析;LAN9252 作为 EtherCAT 物理层(PHY)+ 链路层芯片,处理以太网硬件收发;

  2. 协议层:移植 EtherCAT 从站协议栈(如 SOEM slave/EC-Engineer),实现 EtherCAT 从机状态机、PDO 映射、邮箱通信;

  3. 应用层:STM32 采集传感器数据(如 ADC、GPIO),通过 EtherCAT PDO 实时上传给主站,响应主站指令。

    graph TD
    A[EtherCAT主站] -->|以太网| B[LAN9252(EtherCAT PHY)]
    B -->|SPI/并行| C[STM32主控]
    C --> D[数据采集模块]
    D --> D1[ADC模拟量采集]
    D --> D2[GPIO数字量采集]
    C --> E[EtherCAT从站协议栈]
    E --> F[PDO数据映射/传输]

二、硬件选型与连接

1. 核心器件
器件 选型建议 理由
STM32 STM32F407/STM32H743 主频高(168MHz+/400MHz),有足够资源跑 EtherCAT 协议栈
LAN9252 Microchip LAN9252i/9252 原生支持 EtherCAT,SPI / 并行接口,集成 PHY,无需额外网络变压器
采集模块 模拟量(ADC)/ 数字量(GPIO) 根据需求选,如 4-20mA 采集、DI/DO
2. 硬件连接(STM32F407 + LAN9252)
  • 通信接口 :LAN9252 默认用 SPI 与 STM32 通信(推荐,接线少):
    • LAN9252_SPI_SCK → STM32_SPIx_SCK(如 SPI2_SCK: PB13)
    • LAN9252_SPI_MOSI → STM32_SPIx_MOSI(PB15)
    • LAN9252_SPI_MISO → STM32_SPIx_MISO(PB14)
    • LAN9252_SPI_CS → STM32_GPIO(PB12,片选)
    • LAN9252_INT → STM32_EXTI(PA0,中断引脚,接收 LAN9252 的中断)
  • 电源:LAN9252 需 3.3V 供电,STM32 核心 3.3V,模拟采集需 5V/12V(外部供电);
  • 以太网口:LAN9252 的 RX+/RX-/TX+/TX - 接 RJ45 网口(带隔离变压器);
  • 数据采集:STM32 ADC 通道(如 PA0-PA7)接模拟传感器,GPIO(如 PB0-PB7)接数字量输入。

三、软件实现步骤(基于 STM32CubeIDE)

1. 环境准备
  • 开发工具:STM32CubeIDE(最新版)、STM32CubeMX;
  • 协议栈:移植SOEM(Simple Open EtherCAT Master/Slave) 从站版本,或 Microchip 官方 LAN9252 EtherCAT 从站驱动;
  • 调试工具:EtherCAT 主站软件(如倍福 Twincat 3、SOEM Master)、串口调试器、示波器。
2. 底层驱动开发
(1)LAN9252 驱动(SPI 通信)
复制代码
#include "lan9252.h"
#include "spi.h"

// LAN9252寄存器读写函数
void LAN9252_WriteReg(uint16_t reg, uint32_t data) {
    uint8_t tx_buf[6] = {0};
    // 写命令格式:0x00 + 寄存器地址(2字节) + 数据(4字节)
    tx_buf[0] = 0x00;
    tx_buf[1] = (reg >> 8) & 0xFF;
    tx_buf[2] = reg & 0xFF;
    tx_buf[3] = (data >> 24) & 0xFF;
    tx_buf[4] = (data >> 16) & 0xFF;
    tx_buf[5] = (data >> 8) & 0xFF;
    tx_buf[6] = data & 0xFF;
    
    HAL_GPIO_WritePin(LAN9252_CS_GPIO_Port, LAN9252_CS_Pin, GPIO_PIN_RESET); // 片选拉低
    HAL_SPI_Transmit(&hspi2, tx_buf, 7, 100); // SPI2通信
    HAL_GPIO_WritePin(LAN9252_CS_GPIO_Port, LAN9252_CS_Pin, GPIO_PIN_SET); // 片选拉高
}

uint32_t LAN9252_ReadReg(uint16_t reg) {
    uint8_t tx_buf[3] = {0};
    uint8_t rx_buf[4] = {0};
    uint32_t data = 0;
    
    // 读命令格式:0x01 + 寄存器地址(2字节)
    tx_buf[0] = 0x01;
    tx_buf[1] = (reg >> 8) & 0xFF;
    tx_buf[2] = reg & 0xFF;
    
    HAL_GPIO_WritePin(LAN9252_CS_GPIO_Port, LAN9252_CS_Pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi2, tx_buf, 3, 100); // 发送读命令
    HAL_SPI_Receive(&hspi2, rx_buf, 4, 100);   // 接收4字节数据
    HAL_GPIO_WritePin(LAN9252_CS_GPIO_Port, LAN9252_CS_Pin, GPIO_PIN_SET);
    
    data = (rx_buf[0] << 24) | (rx_buf[1] << 16) | (rx_buf[2] << 8) | rx_buf[3];
    return data;
}

// LAN9252初始化(配置EtherCAT模式、PHY)
void LAN9252_Init(void) {
    // 软复位LAN9252
    LAN9252_WriteReg(LAN9252_REG_RESET, 0x00000001);
    HAL_Delay(100);
    
    // 配置为EtherCAT从站模式,启用SPI接口
    LAN9252_WriteReg(LAN9252_REG_MODE, 0x00000002);
    
    // 启用PHY,自动协商速率
    LAN9252_WriteReg(LAN9252_REG_PHY_CTRL, 0x00000001);
}

(2)数据采集驱动(ADC+GPIO)

复制代码
#include "adc.h"
#include "gpio.h"

// 模拟量采集(单次转换)
float ADC_Read_Channel(uint32_t channel) {
    ADC_ChannelConfTypeDef sConfig = {0};
    
    // 配置ADC通道
    sConfig.Channel = channel;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
        Error_Handler();
    }
    
    // 启动ADC转换并读取值
    HAL_ADC_Start(&hadc1);
    if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
        uint32_t adc_val = HAL_ADC_GetValue(&hadc1);
        // 转换为电压值(3.3V参考,12位ADC)
        float voltage = (adc_val * 3.3f) / 4095.0f;
        return voltage;
    }
    return 0.0f;
}

// 数字量采集(GPIO输入)
uint8_t GPIO_Read_DI(uint16_t pin) {
    return HAL_GPIO_ReadPin(GPIOA, pin);
}

// 数据采集主函数(采集4路模拟量+4路数字量)
void DataAcquisition(uint32_t *analog_data, uint8_t *digital_data) {
    // 采集4路模拟量(ADC1_CH0~CH3)
    analog_data[0] = (uint32_t)(ADC_Read_Channel(ADC_CHANNEL_0) * 1000); // 转换为mV,便于传输
    analog_data[1] = (uint32_t)(ADC_Read_Channel(ADC_CHANNEL_1) * 1000);
    analog_data[2] = (uint32_t)(ADC_Read_Channel(ADC_CHANNEL_2) * 1000);
    analog_data[3] = (uint32_t)(ADC_Read_Channel(ADC_CHANNEL_3) * 1000);
    
    // 采集4路数字量(GPIOA_PIN4~PIN7)
    digital_data[0] = GPIO_Read_DI(GPIO_PIN_4);
    digital_data[1] = GPIO_Read_DI(GPIO_PIN_5);
    digital_data[2] = GPIO_Read_DI(GPIO_PIN_6);
    digital_data[3] = GPIO_Read_DI(GPIO_PIN_7);
}
3. EtherCAT 从站协议栈移植(SOEM Slave)

SOEM(Simple Open EtherCAT Master)是开源 EtherCAT 协议栈,支持从站模式,核心步骤:

  1. 移植 SOEM 从站代码:将 SOEM 的 slave 目录下的文件加入工程,适配 STM32 的时钟、中断;

  2. 配置 PDO 映射:定义过程数据对象(PDO),将采集的模拟量 / 数字量映射到 PDO 通信区:

    // PDO映射定义(从站字典)
    typedef struct {
    // 输出PDO(主站→从站,如控制指令)
    uint8_t control_cmd; // 1字节控制命令
    // 输入PDO(从站→主站,采集数据)
    uint32_t analog_data[4]; // 4路模拟量(mV)
    uint8_t digital_data[4]; // 4路数字量
    } EtherCAT_Slave_PDO;

    EtherCAT_Slave_PDO ec_pdo; // PDO通信结构体

    // EtherCAT从站初始化
    void EtherCAT_Slave_Init(void) {
    // 初始化SOEM协议栈
    ec_slave_init(&hspi2, LAN9252_INT_Pin);
    // 配置PDO映射表
    ec_pdo_map_init();
    // 启动EtherCAT通信
    ec_slave_start();
    }

    // EtherCAT数据更新(主循环调用)
    void EtherCAT_UpdateData(void) {
    // 1. 读取主站下发的控制指令(输出PDO)
    ec_pdo.control_cmd = ec_slave_read_output(0, 0, 1);

    复制代码
     // 2. 采集数据并写入输入PDO
     DataAcquisition(ec_pdo.analog_data, ec_pdo.digital_data);
     
     // 3. 将输入PDO数据发送给主站
     ec_slave_write_input(0, 0, sizeof(ec_pdo.analog_data) + sizeof(ec_pdo.digital_data), &ec_pdo.analog_data);

    }

  3. 主程序入口

    int main(void) {
    // 1. 硬件初始化
    HAL_Init();
    SystemClock_Config(); // 配置STM32时钟(F407→168MHz)
    MX_GPIO_Init();
    MX_SPI2_Init();
    MX_ADC1_Init();

    复制代码
     // 2. 外设初始化
     LAN9252_Init();
     EtherCAT_Slave_Init();
     
     // 3. 主循环
     while (1) {
         // 数据采集 + EtherCAT数据更新
         EtherCAT_UpdateData();
         
         // 处理LAN9252中断(如数据收发完成)
         if (HAL_GPIO_ReadPin(LAN9252_INT_GPIO_Port, LAN9252_INT_Pin) == GPIO_PIN_RESET) {
             LAN9252_Interrupt_Handler();
         }
         
         HAL_Delay(10); // 10ms采集一次(可根据需求调整)
     }

    }

四、关键调试步骤

  1. 硬件调试
    • 用万用表检查 LAN9252 供电、SPI 接线是否正确;
    • 用示波器观察 LAN9252_INT 引脚,确认有中断信号(EtherCAT 通信时会周期性触发);
  2. 协议调试
    • 用 Twincat 3 作为 EtherCAT 主站,扫描从站(需配置从站 ESC 地址与 LAN9252 匹配);
    • 查看主站是否能识别从站,PDO 映射是否正确;
  3. 数据调试
    • 给模拟量通道接已知电压(如 1.65V),查看主站接收的数值是否为 1650mV;
    • 切换数字量输入引脚电平,验证主站接收的数字量是否同步变化。

五、注意事项

  1. 时钟精度:EtherCAT 对时钟要求高,STM32 需配置精准的外部晶振(25MHz),避免通信丢包;
  2. SPI 速率:LAN9252 的 SPI 通信速率建议≤20MHz,过高易导致数据错误;
  3. PDO 大小:单次 PDO 传输数据不宜过大(建议≤64 字节),保证实时性;
  4. 容错处理:添加通信超时、数据校验逻辑,避免采集数据异常;
  5. LAN9252 配置:需确保 LAN9252 工作在 EtherCAT 模式(而非普通以太网模式),否则无法解析 EtherCAT 帧。

六、工具与资源推荐

类型 资源名称 用途
协议栈 SOEM(GitHub) 开源 EtherCAT 主 / 从站协议栈
主站调试 Twincat 3(倍福) 专业 EtherCAT 主站软件
硬件手册 LAN9252 Datasheet 寄存器配置、通信时序
STM32 配置 STM32CubeMX 快速生成底层驱动
抓包工具 Wireshark(EtherCAT 插件) 分析 EtherCAT 通信帧

总结

  1. 基于 STM32+LAN9252 的 EtherCAT 从机数据采集系统,核心是 "LAN9252 硬件驱动 + EtherCAT 从站协议栈 + 数据采集逻辑";
  2. 优先选择 STM32F4/H7 系列,移植 SOEM 协议栈实现 PDO 数据传输,保证实时性;
  3. 调试重点是 LAN9252 的 SPI 通信、EtherCAT 从站识别、采集数据的 PDO 映射,需结合主站工具验证。
相关推荐
程序员小寒2 小时前
前端性能优化之白屏、卡顿指标和网络环境采集篇
前端·javascript·网络·性能优化
yezhailiaoke2 小时前
【CANoe测试系列】-程控电源控制
单片机·嵌入式硬件
wal13145202 小时前
OpenClaw教程(九)—— 彻底告别!OpenClaw 卸载不残留指南
前端·网络·人工智能·chrome·安全·openclaw
白藏y3 小时前
【协议】SSE协议和WebSocket协议
网络·websocket·网络协议
运维行者_4 小时前
网络监控方案从零开始 -- 企业级完整指南
大数据·运维·服务器·网络·数据库·人工智能·自动化
朱一头zcy4 小时前
简单理解NAT(网络地址转换)模式和桥接模式
网络·桥接模式·nat
-Springer-5 小时前
STM32 学习 —— 个人学习笔记9-2(USART串口数据包 & 串口收发 HEX 及 文本 数据包)
笔记·stm32·学习
加农炮手Jinx5 小时前
Flutter 三方库 cloudflare 鸿蒙云边协同分发流适配精讲:直连全球高速存储网关阵列无缝吞吐海量动静态画像资源,构筑大吞吐业务级网络负载安全分流-适配鸿蒙 HarmonyOS ohos
网络·flutter·harmonyos
坚定的共产主义生产设备永不宕机5 小时前
动态路由协议
网络