面向需要手动从 ESI XML 搬运数据到 IgH/SOEM C 代码的工程师,兼顾认知学习与查阅需求。按照“理解结构 → 提取信息 → 填入代码 → 工具验证 → 排障”顺序组织,快速完成从硬件描述到主站配置的闭环。
L6N_V1.08.xml 是 L6N 伺服驱动器的 ESI (EtherCAT Slave Information) 设备描述文件,也称为”设备字典”或”XML 描述文件”。它与 ec_slave_config.h 文件是完全对应 的关系。
快速导航
0. 准备与工具
项目
说明
推荐工具
ESI XML 文件
厂商提供的设备描述文件 (通常位于 ../ethercat/master/slaves/ 或驱动光盘)
VS Code + XML 插件、xmllint
参考文档
厂商设备手册,确认 PDO/对象含义与单位
PDF 阅读器
命令行工具
IgH ethercat CLI、xmllint/xpath
ethercat slaves/pdos/cstruct
主站代码
ec_slave_config.h/c、ec_domain_reg_pdo_entry_list 注册表等
GCC/Clang
解析前确保 XML 与驱动固件版本一致;部分厂商会在 RevisionNo 变化时更新 PDO 定义。
1. ESI XML 架构总览 典型结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <EtherCATInfo > <Vendor > <Id > 17185</Id > <Name > INOVANCE</Name > </Vendor > <Descriptions > <Devices > <Device > <Type ProductCode ="#xE2" RevisionNo ="1" > L6N</Type > <RxPdos > ...</RxPdos > <TxPdos > ...</TxPdos > <SyncManagers > ...</SyncManagers > <Dc > ...</Dc > </Device > </Devices > </Descriptions > </EtherCATInfo >
关键节点:
节点
作用
<Vendor>/<Id>
厂商 ID (十进制)
<Type ProductCode="..." RevisionNo="...">
产品码、固件版本
<RxPdos>/<TxPdos>
每个 PDO 及其 Entry 定义
<SyncManagers>/<Sm>
SM 起始地址、方向、看门狗
<Dc>
分布式时钟设置 (部分驱动提供)
使用 XML XPath (xpath -e "//Device[@Name='L6N']" file.xml) 可快速定位目标设备。
2. 设备识别信息 2.1 XML 示例 1 2 3 4 5 6 <Device > <Type ProductCode ="#xE2" RevisionNo ="#x00000001" > L6N</Type > <Vendor > <Id > 17185</Id > </Vendor > </Device >
2.2 C 代码 1 2 3 4 5 6 7 8 9 10 11 #define L6N 0x00004321, 0x000000e2 #define L6N_VENDOR_ID 0x00004321 #define L6N_PRODUCT_CODE 0x000000e2 #define L6N_REVISION_NO 0x00000001
注意:部分驱动要求 RevisionNo 也匹配;IgH 可传入 ecrt_master_slave_config(master, alias, position, vendor, product | (revision << 32))(若使用扩展接口)。
3. PDO 映射分解 3.1 RxPDO (主站→从站) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <RxPdo Fixed ="0" Sm ="2" > <Index > #x1600</Index > <Name > Receive PDO 1</Name > <Entry > <Index > #x6040</Index > <SubIndex > 0</SubIndex > <BitLen > 16</BitLen > <Name > Control word</Name > <DataType > UINT</DataType > </Entry > <Entry > <Index > #x607a</Index > <SubIndex > 0</SubIndex > <BitLen > 32</BitLen > <Name > Profile target position</Name > <DataType > DINT</DataType > </Entry > <Entry > <Index > #x60b8</Index > <SubIndex > 0</SubIndex > <BitLen > 16</BitLen > <Name > Touch Probe Function</Name > <DataType > UINT</DataType > </Entry > </RxPdo >
1 2 3 4 5 6 7 8 9 10 11 12 13 ec_pdo_entry_info_t slave_0_pdo_entries[] = { {0x6040 , 0x00 , 16 }, {0x607a , 0x00 , 32 }, {0x60b8 , 0x00 , 16 }, }; ec_pdo_info_t slave_0_pdos[] = { {0x1600 , 3 , slave_0_pdo_entries + 0 }, };
XML 字段
对应 C 代码
<RxPdo>/<Index>
ec_pdo_info_t.index (0x1600)
<Entry>/<Index>
ec_pdo_entry_info_t.index
<Entry>/<SubIndex>
...subindex
<Entry>/<BitLen>
...bit_length
<RxPdo Fixed="0" Sm="2">
ec_sync_info_t 中 index=2、方向 OUTPUT
3.2 TxPDO (从站→主站) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <TxPdo Fixed ="0" Sm ="3" > <Index > #x1a00</Index > <Name > Transmit PDO 1</Name > <Entry > <Index > #x603F</Index > <SubIndex > #x00</SubIndex > <BitLen > 16</BitLen > <Name > Last error code</Name > <DataType > UINT</DataType > </Entry > <Entry > <Index > #x6041</Index > <SubIndex > 0</SubIndex > <BitLen > 16</BitLen > <Name > Status word</Name > <DataType > UINT</DataType > </Entry > <Entry > <Index > #x6061</Index > <SubIndex > #x00</SubIndex > <BitLen > 8</BitLen > <Name > Modes of operation display</Name > <DataType > SINT</DataType > </Entry > <Entry > <Index > #x6064</Index > <SubIndex > 0</SubIndex > <BitLen > 32</BitLen > <Name > Actual motor position</Name > <DataType > DINT</DataType > </Entry > </TxPdo >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ec_pdo_entry_info_t slave_0_pdo_entries[] = { {0x603f , 0x00 , 16 }, {0x6041 , 0x00 , 16 }, {0x6061 , 0x00 , 8 }, {0x6064 , 0x00 , 32 }, {0x60b9 , 0x00 , 16 }, {0x60ba , 0x00 , 32 }, {0x60fd , 0x00 , 32 }, }; ec_pdo_info_t slave_0_pdos[] = { {0x1600 , 3 , slave_0_pdo_entries + 0 }, {0x1a00 , 7 , slave_0_pdo_entries + 3 }, };
注意 : TxPDO 在 XML 中有 9 个入口,但 ec_slave_config.h 只使用了其中 7 个(根据实际需求选择)。
3.3 位宽与类型映射
BitLen
常用类型
IgH 宏
8
uint8_t/int8_t
EC_READ_U8/EC_WRITE_U8
16
uint16_t/int16_t
EC_READ_U16/EC_WRITE_U16
32
uint32_t/int32_t
EC_READ_U32/EC_WRITE_S32
保持与驱动文档相同的有符号/无符号类型,避免溢出。若 BitLen 不是 8 的倍数,需确认厂商自定义位域并按位操作。
3.4 多 PDO/多 Entry 的数组布局 1 2 3 4 5 6 7 8 9 10 11 static ec_pdo_entry_info_t l6n_pdo_entries[] = { {0x6040 , 0x00 , 16 }, {0x607A , 0x00 , 32 }, {0x6041 , 0x00 , 16 }, {0x6064 , 0x00 , 32 }, }; static ec_pdo_info_t l6n_pdos[] = { {0x1600 , 2 , l6n_pdo_entries + 0 }, {0x1A00 , 2 , l6n_pdo_entries + 2 }, };
n_entries 必须与 XML 中 <Entry> 数量一致;指针偏移按顺序累加。
3.5 Domain 注册所需数据 1 2 3 4 5 6 7 8 9 10 11 12 static unsigned int off_ctrl_word;static unsigned int off_target_pos;static unsigned int off_status_word;static unsigned int off_actual_pos;const ec_pdo_entry_reg_t domain_regs[] = { {0 , 0 , L6N_VENDOR_ID, L6N_PRODUCT_CODE, 0x6040 , 0x00 , &off_ctrl_word}, {0 , 0 , L6N_VENDOR_ID, L6N_PRODUCT_CODE, 0x607A , 0x00 , &off_target_pos}, {0 , 0 , L6N_VENDOR_ID, L6N_PRODUCT_CODE, 0x6041 , 0x00 , &off_status_word}, {0 , 0 , L6N_VENDOR_ID, L6N_PRODUCT_CODE, 0x6064 , 0x00 , &off_actual_pos}, {} };
ec_pdo_entry_reg_t 与 XML 的对应:VendorId、ProductCode、Index、SubIndex。alias/position 默认 0 表示匹配所有。
4. Sync Manager (SM) 配置 4.1 XML 示例 1 2 3 4 5 6 7 8 9 <Sm Enable ="1" StartAddress ="#x1000" ControlByte ="#x26" DefaultSize ="124" MinSize ="40" MaxSize ="256" > MBoxOut</Sm > <Sm Enable ="1" StartAddress ="#x1100" ControlByte ="#x22" DefaultSize ="124" MinSize ="40" MaxSize ="256" > MBoxIn</Sm > <Sm Enable ="1" StartAddress ="#x1200" ControlByte ="#x64" MaxSize ="100" > Outputs</Sm > <Sm Enable ="1" StartAddress ="#x1400" ControlByte ="#x20" MaxSize ="100" > Inputs</Sm >
1 2 3 4 5 6 7 8 ec_sync_info_t slave_0_syncs[] = { {0 , EC_DIR_OUTPUT, 0 , NULL , EC_WD_DISABLE}, {1 , EC_DIR_INPUT, 0 , NULL , EC_WD_DISABLE}, {2 , EC_DIR_OUTPUT, 1 , slave_0_pdos + 0 , EC_WD_ENABLE}, {3 , EC_DIR_INPUT, 1 , slave_0_pdos + 1 , EC_WD_DISABLE}, {0xff } };
XML 字段
IgH 参数
Sm 顺序
sync_index (0,1,2,3)
ControlByte 位 2 (0x04)
方向 (Output/Input)
Enable
是否启用 SM,通常 1
PdoCount & <Pdo>
n_pdos + ec_pdo_info_t 指针
<Watchdog> (若有)
EC_WD_ENABLE/EC_WD_DISABLE
某些厂商会提供 SM4/SM5(如附加诊断 PDO),需按 XML 顺序追加;若 ControlByte 显示与默认不同,请保持一致。
对应关系 :
SM0/SM1: 邮箱通信 (CoE, SDO)
SM2: RxPDO (主站 → 从站数据)
SM3: TxPDO (从站 → 主站数据)
5. 从 XML 到 C 代码的映射流程
定位设备 :在 XML 中搜索 <Type> 名称或 ProductCode。
抄写 ID :记录 <Vendor>/<Id>、ProductCode、RevisionNo。
整理 PDO :
分别列出 <RxPdo>、<TxPdo>。
逐条摘取 Entry (Index/SubIndex/BitLen/Name)。
计算累计位宽,确认 8-bit 对齐。
生成数组 :
ec_pdo_entry_info_t:按顺序填入所有 Entry。
ec_pdo_info_t:每个 PDO 记录索引、条目数、entries 起始指针。
配置 SM :按照 <Sm> 顺序创建 ec_sync_info_t。
注册 Domain :为需要读写的 Entry 填写 ec_pdo_entry_reg_t,获取偏移量。
验证 :与 ethercat cstruct -p 输出或 ethercat pdos -p 结果对比,确保一致。
5.1. 设备识别信息 1 2 3 4 <Vendor > <Id > 17185</Id > ← Vendor ID (0x4321) </Vendor > <Type ProductCode ="#xE2" RevisionNo ="1" > ← Product Code & Revision
用途 : 用于在程序中识别和配置从站设备
5.2. PDO 映射信息 (最重要!) RxPDO - 控制命令 1 2 3 4 5 6 7 8 9 <RxPdo > <Index > #x1600</Index > ← PDO映射索引 <Entry > <Index > #x6040</Index > ← 对象字典索引 <SubIndex > 0</SubIndex > ← 子索引 <BitLen > 16</BitLen > ← 数据长度(位) <DataType > UINT</DataType > ← 数据类型 </Entry > </RxPdo >
提取内容 :
PDO 索引 (0x1600, 0x1601…)
每个 Entry 的对象索引、子索引、位长度
数据类型(用于正确读写)
TxPDO - 状态反馈 1 2 3 4 5 6 7 8 <TxPdo > <Index > #x1a00</Index > ← PDO映射索引 <Entry > <Index > #x6041</Index > ← 状态字 <Index > #x6064</Index > ← 实际位置 </Entry > </TxPdo >
5.3. 对象字典详细信息 在 XML 的 <Dictionary> 部分可以找到每个对象的详细说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <Object > <Index > #x6040</Index > <Name > Control word</Name > <Type > UINT</Type > <BitSize > 16</BitSize > <Info > <DefaultValue > 0</DefaultValue > </Info > <Entry > <Index > #x6040</Index > <SubIndex > 0</SubIndex > <BitLen > 16</BitLen > <Name > Control word</Name > <DataType > UINT</DataType > <Flags > <Access > rw</Access > ← 读写权限 <PdoMapping > r</PdoMapping > ← PDO映射方式 </Flags > </Entry > </Object >
重要字段说明 :
Access: 访问权限 (ro=只读, rw=读写, wo=只写)
PdoMapping: PDO 映射类型 (r=RxPDO, t=TxPDO)
DefaultValue: 默认值
MinValue/MaxValue: 取值范围
5.4. 支持的运行模式 1 2 3 4 5 6 7 8 9 <Entry > <Index > #x6060</Index > <Name > Modes of operation</Name > </Entry >
5.5. 编码器参数 1 2 3 4 5 6 7 <Object > <Index > #x608F</Index > <Name > Position encoder resolution</Name > <SubIndex > 1</SubIndex > <Name > Encoder increments</Name > </Object >
用途 : 确定 MOTOR_ENCODER_BITS 的值
5.6. 速度和加速度限制 1 2 3 4 5 6 7 8 9 10 11 <Object > <Index > #x6080</Index > <Name > Max motor speed</Name > <DataType > UDINT</DataType > </Object > <Object > <Index > #x60C5</Index > <Name > Max acceleration</Name > <DataType > UDINT</DataType > </Object >
用途 : 设置合理的控制参数上限
5.7. 分布时钟配置 1 2 <Fmmu Sm ="2" > Outputs</Fmmu > <Fmmu Sm ="3" > Inputs</Fmmu >
用途 : 了解哪些 SM 支持分布时钟
5.8. 错误代码定义 1 2 3 4 5 <Object > <Index > #x603F</Index > <Name > Error code</Name > </Object >
5.9. 数字 I/O 配置 1 2 3 4 5 <Entry > <Index > #x60FD</Index > <Name > Digital inputs</Name > <BitLen > 32</BitLen > </Entry >
5.10 单位转换信息 1 2 3 4 <Object > <Index > #x6089</Index > <Name > Position notation index</Name > </Object >
6、如何从 XML 生成 ec_slave_config.h 方法 1: 手动提取 (当前方法) 步骤 :
打开 XML 文件
找到 <RxPdo> 和 <TxPdo> 部分
提取每个 <Entry> 的索引和位长度
按照 IgH EtherCAT Master 的格式编写 C 代码
优点 : 精确控制,只包含需要的对象缺点 : 繁琐,容易出错
方法 2: 使用 ethercat 命令行工具 IgH EtherCAT Master 提供了自动工具:
1 2 3 4 5 6 7 8 9 ethercat cstruct -p 0
优点 : 自动生成,快速准确缺点 : 需要硬件连接
方法 3: 使用 TwinCAT/CODESYS 工具 使用图形化工具:
导入 XML 文件到 TwinCAT
配置 PDO 映射
导出为 C 代码或使用工具生成
7、XML 中的核心对象字典 (CiA 402) 常用对象索引对照表
索引
名称
类型
访问
说明
通信控制
0x6040
Controlword
UINT16
RW
控制字
0x6041
Statusword
UINT16
RO
状态字
0x603F
Error Code
UINT16
RO
错误代码
运行模式
0x6060
Modes of Operation
INT8
RW
运行模式设置
0x6061
Modes Display
INT8
RO
运行模式显示
位置控制
0x607A
Target Position
INT32
RW
目标位置 (PP/CSP)
0x6064
Position Actual
INT32
RO
实际位置
0x60F4
Position Error
INT32
RO
位置误差
速度控制
0x60FF
Target Velocity
INT32
RW
目标速度 (PV/CSV)
0x606C
Velocity Actual
INT32
RO
实际速度
转矩控制
0x6071
Target Torque
INT16
RW
目标转矩
0x6077
Torque Actual
INT16
RO
实际转矩
限制参数
0x6080
Max Motor Speed
UINT32
RW
最大速度
0x607F
Max Profile Velocity
UINT32
RW
轮廓最大速度
0x60C5
Max Acceleration
UINT32
RW
最大加速度
探针功能
0x60B8
Touch Probe Function
UINT16
RW
探针功能
0x60B9
Touch Probe Status
UINT16
RO
探针状态
0x60BA
Touch Probe Pos1
INT32
RO
探针位置 1
数字 I/O
0x60FD
Digital Inputs
UINT32
RO
数字输入
0x60FE
Digital Outputs
UINT32
RW
数字输出
8、实际应用示例 示例 1: 添加速度反馈到 PDO 步骤 1: 在 XML 中查找 1 2 3 4 5 6 7 <Object > <Index > #x606C</Index > <Name > Velocity actual value</Name > <Type > DINT</Type > <BitSize > 32</BitSize > </Object >
步骤 2: 检查是否可以映射到 PDO 查找 <Flags> 部分:
1 2 3 4 <Flags > <Access > ro</Access > <PdoMapping > t</PdoMapping > ← "t" 表示可以映射到 TxPDO </Flags >
步骤 3: 添加到 ec_slave_config.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ec_pdo_entry_info_t slave_0_pdo_entries[] = { {0x606C , 0x00 , 32 }, }; ec_pdo_info_t slave_0_pdos[] = { {0x1600 , 3 , slave_0_pdo_entries + 0 }, {0x1a00 , 8 , slave_0_pdo_entries + 3 }, }; typedef struct { unsigned int velocity_actual_value; } EC_SERVO_offset; static ec_pdo_entry_reg_t domain0_regs[] = { {POS_SERVO_0, EC_SERVO_DEVICE, 0x606C , 0 , &offsetOfEC_SERVO_0.velocity_actual_value}, {} };
示例 2: 修改为速度控制模式 步骤 1: 在 XML 中找到速度模式的 PDO 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <RxPdo Fixed ="0" > <Index > #x1601</Index > <Name > Receive PDO 2</Name > <Entry > <Index > #x6040</Index > ... </Entry > <Entry > <Index > #x60ff</Index > <SubIndex > 0</SubIndex > <BitLen > 32</BitLen > <Name > Target velocity</Name > <DataType > DINT</DataType > </Entry > <Entry > <Index > #x6060</Index > ... </Entry > </RxPdo >
步骤 2: 修改 ec_slave_config.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ec_pdo_entry_info_t slave_0_pdo_entries[] = { {0x6040 , 0x00 , 16 }, {0x60ff , 0x00 , 32 }, {0x6060 , 0x00 , 8 }, {0x6041 , 0x00 , 16 }, {0x606C , 0x00 , 32 }, }; ec_pdo_info_t slave_0_pdos[] = { {0x1601 , 3 , slave_0_pdo_entries + 0 }, {0x1a01 , 2 , slave_0_pdo_entries + 3 }, };
9. 常见问题排障 Q1: XML 中有多个 RxPDO/TxPDO,用哪个? A :
不同的 PDO 对应不同的运行模式
0x1600/0x1a00: 通常是位置模式 (CSP/PP)
0x1601/0x1a01: 通常是速度模式 (CSV/PV)
0x1602/0x1a02: 可能是转矩模式 (CST)
选择方法 : 根据你的应用需求选择
Q2: ec_slave_config.h 中的 PDO 数量和 XML 不一致? A :
这是正常的 !
XML 列出了所有可能 的 PDO 入口
C 代码中只需要包含实际使用 的入口
可以减少通信数据量,提高效率
Q3: 如何验证配置是否正确? A : 使用 ethercat 命令行工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ethercat pdos -p 0 ethercat pdos -v -p 0
Q4: XML 中没有找到某个对象? A :
使用 XML 编辑器搜索索引 (如 0x6040)
检查 <Dictionary> 部分
某些对象可能通过 SDO 访问,不在 PDO 中
查阅驱动器手册确认是否支持
Q5: 如何添加 SDO 配置参数? A : SDO 不在 PDO 中,需要在初始化时配置:
1 2 3 uint8_t mode = 8 ; ecrt_master_sdo_download(master, 0 , 0x6060 , 0 , &mode, sizeof (mode), NULL );
或在 XML 中查看 <InitCmd> 部分的示例。
现象
可能原因
检查命令/方法
解决建议
Failed to configure slave: vendor/product mismatch
ID/产品码写错(十进制/十六进制混淆)
ethercat slaves、XML 对照
用 printf("0x%08X\n", vendor) 验证;注意大小写和填充
PDO entry size mismatch
BitLen 与代码类型不符、指针偏移错
ethercat pdos、dmesg
逐条核对 BitLen,确保 n_entries 正确;重新生成数组
SM watchdog 报警
EC_WD_ENABLE 配置不当或任务周期过长
dmesg、驱动面板
若应用未实现看门狗,设置 EC_WD_DISABLE 或在周期任务内喂狗
Config PDO failed
XML 中的 PDO 被厂商锁定 (Fixed=1) 或不支持重映射
ethercat pdos 查看 Fixed 标志
若 Fixed=1,必须按厂家默认映射使用;考虑通过 SDO 启用可编程映射
数据错位/值异常
Domain 注册顺序与写入顺序不匹配、大小端问题
打印 offset 值、Wireshark 抓包
确保读写宏与 BitLen/符号匹配,必要时在代码中添加 static_assert
设备无法进入 OP
SM/ PDO 未全部配置或 DC 设置错误
ethercat diag -p、dmesg
先禁用 DC,确认 PDO 映射与 SM 对应正确,再逐项恢复
通过以上步骤,便可将任意厂商的 ESI XML 转换为主站可用的 C 结构体,并借助工具快速验证和排错。如需自动化,可进一步编写脚本解析 XML 并生成 ec_pdo_entry_info_t/ec_sync_info_t 代码模板。
总结 XML 字典文件的作用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ┌─────────────────────────────────────────┐ │ L6N_V1.08.xml │ │ (厂商提供的设备描述) │ └─────────────────┬───────────────────────┘ │ │ 提取信息 ▼ ┌─────────────────────────────────────────┐ │ 我们需要获取的关键信息: │ │ │ │ 1. Vendor ID & Product Code (识别) │ │ 2. PDO 映射 (数据交换配置) │ │ 3. 对象字典 (参数说明) │ │ 4. 数据类型和范围 │ │ 5. 访问权限 │ │ 6. 默认值和限制 │ └─────────────────┬───────────────────────┘ │ │ 转换为 ▼ ┌─────────────────────────────────────────┐ │ ec_slave_config.h │ │ (C代码配置文件) │ │ │ │ - ec_pdo_entry_info_t │ │ - ec_pdo_info_t │ │ - ec_sync_info_t │ │ - EC_SERVO_offset │ │ - domain_regs[] │ └─────────────────────────────────────────┘
关键要点
XML 是源头 : 所有配置信息的权威来源
完全对应 : ec_slave_config.h 必须与 XML 一致
可以裁剪 : 只包含实际需要的 PDO 入口
验证重要 : 使用工具验证配置正确性