ECAN-Lite 技术手册 V2.2
EtherCAT 转 4 路 CAN/CAN FD 动态 PDO 网关
目录与阅读路径
本手册面向需要集成 ECAN-Lite 的用户,而不是只描述内部实现。读者应能根据本文完成以下闭环:识别产品能力、配置 EtherCAT PDO/SDO、进入 OP、在 RxPDO 中下发 CAN/CAN FD 帧、从 TxPDO 中读取 CAN/CAN FD 帧,并在异常时定位问题。
本手册按“先集成、再实现、再诊断”的顺序组织。前半部分说明 EtherCAT/PDO/SDO 协议边界,后半部分说明 IgH 示例、二次开发和现场排查。
从零到收发 CAN 帧
按任务阅读
章节分工
完全不使用 IgH 时,优先阅读 5.4 和 5.4.3 。使用 IgH 主站库但不直接运行本仓库 demo 时,优先阅读 15.4 和 15.5 。
1. 产品定位
ECAN-Lite 是一款 EtherCAT 到 CAN/CAN FD 的实时网关模块。设备作为 EtherCAT 从站运行,主站通过 RxPDO 下发 CAN/CAN FD 发送请求,设备通过 TxPDO 上传 CAN/CAN FD 接收帧、发送结果和紧凑通道状态。
本版本采用新的动态 PDO 协议:TxPDO 和 RxPDO 均以 128B * N 为单位独立配置,N=1..24,单方向最大 3072B。PDO 内容不再采用固定通道固定槽的旧布局,而是统一使用“两层结构”:
text Copy FixedPdoFrameHeader[24B] + FramePacketStream[ActivePDOBytes - 24]24B 固定头部用于版本/头长、双序号提交、帧区长度、payload CRC16、布局标识、通道掩码、帧数量、溢出计数和 4 路压缩状态;后续帧区是连续的 CAN/CAN FD 帧封装包。每个帧包以 2B 控制字自描述后续 CAN ID、时间戳和数据长度,因此主站解析不依赖旧的固定槽位。
2. 核心特性
3. 方向定义
TxPDO 与 RxPDO 是完全独立的方向。每个方向可独立选择 PDO 大小倍数、通道掩码、封装 profile、预算策略和方向选项。通道开启与 PDO 大小是两个正交维度:关闭某个 CAN 通道不会改变 SM2/SM3 长度,只会改变 active channel mask 和调度预算。
理解本文时可以把协议分成三层:
如果只想先跑通收发,可以先按第 5.4.3 和 5.4.4.1 完成一帧下发;当需要自己实现解析库时,再回到第 6..12 章逐字段阅读。
3.1 文档标记说明
本文后续表格使用以下标记:
PDO 表格中的 访问 指主站对过程数据的访问方式:RxPDO/SM2 为主站写,从站读;TxPDO/SM3 为从站写,主站读。SDO 表格中的 访问 指主站通过 CoE 对对象字典子项的访问属性。
4. 系统架构
text Copy EtherCAT Master
|
| SM2 RxPDO: Fixed Header + FramePacketStream
| SM3 TxPDO: Fixed Header + FramePacketStream
v
+------------------------------+
| ECAN-Lite EtherCAT Slave |
| SSC + CoE + FoE |
| Dynamic PDO Parser/Packer |
| Byte Budget Scheduler |
+-----+-----+-----+-----+------+
| | | |
CAN0 CAN1 CAN2 CAN3
5. EtherCAT PDO 映射与大小
5.1 128B Chunk 映射
PDO 映射按 128B chunk 拼接。每个 chunk 在对象字典中拆成 8 个 STRING(16) 映射单元,以避免 PDO mapping entry 的 bit length 限制。
text Copy RxPDO chunk maps: 0x1600..0x1617
TxPDO chunk maps: 0x1A00..0x1A17
SM2 assignment: 0x1C12 选择前 N 个 RxPDO chunk
SM3 assignment: 0x1C13 选择前 N 个 TxPDO chunkchunk 是 EtherCAT 映射和长度选择单位,不是协议解析层。FramePacketStream 可以跨 128B chunk 边界,接收端只按固定头部中的 payload_len 解析有效帧区。
5.1.1 多个 chunk 在主站侧如何拼接
主站侧不要把 0x1600..0x1617 / 0x1A00..0x1A17 当成多段独立协议解析。它们只是为了适配 EtherCAT PDO mapping 限制而拆出的 128B 映射块。应用层应把同一方向的前 N 个 chunk 按 assignment 顺序拼成一个连续 byte buffer:
text Copy RxPDO/SM2 output buffer:
chunk0[128B] + chunk1[128B] + ... + chunkN-1[128B]
其中 ... 表示省略中间连续 chunk,顺序和大小均按 128B 递推
TxPDO/SM3 input buffer:
chunk0[128B] + chunk1[128B] + ... + chunkN-1[128B]
其中 ... 表示省略中间连续 chunk,顺序和大小均按 128B 递推每个 128B chunk 又由 8 个 STRING(16) 映射单元组成。主站如果把它们暴露成多个变量,应用需要按以下顺序复制:
text Copy for chunk = 0 .. N-1:
for unit = 0 .. 7:
dst_offset = chunk * 128 + unit * 16
copy 16 bytes to/from process image entry下面表格完整展开 chunk=0 的 8 个映射单元,并用省略行表示后续 chunk 按相同规律递推。完整关系以随后公式为准。
完整映射规律:
通用公式:
text Copy unit_index = chunk * 8 + unit
offset = unit_index * 16
RxPDO 数据对象 index = 0x7000 + unit_index * 0x10
TxPDO 数据对象 index = 0x6000 + unit_index * 0x10因此 chunk=1 时并不只有 unit=0。例如 RxPDO 0x1601 实际包含 0x7080, 0x7090, ..., 0x70F0 八个 16B 单元,其中 ... 表示省略中间按 0x10 递增的对象;TxPDO 0x1A01 实际包含 0x6080, 0x6090, ..., 0x60F0 八个 16B 单元,其中 ... 同样表示省略中间按 0x10 递增的对象。
例如 N=3 时,每个方向的连续 buffer 为 384B:
text Copy chunk0: offset 0..127
chunk1: offset 128..255
chunk2: offset 256..383固定 24B 头部位于连续 buffer 的 offset 0。帧封装区从 offset 24 开始,到 128*N-1 结束。CAN_FRAME / TX_RESULT 包允许跨 chunk 边界,主站解析时只应根据固定头部中的 payload_len 和 CRC 判断有效区域,不应在 128B 边界重新开始解析。
在 TwinCAT、CODESYS 或自研主站中,如果工具支持将 PDO 映射直接映射为连续 Byte Array,推荐直接建立 ARRAY[0..128*N-1] OF BYTE。如果工具只能把每个 STRING(16) 暴露为单独变量,则按上面的 offset 公式在应用层拼接和拆分。
5.2 PDO 大小倍数
text Copy ActivePDOBytes = 128 * PdoSizeMultiplier
ActiveFrameAreaBytes = ActivePDOBytes - 24
PdoSizeMultiplier: 1..24
推荐值应按 CAN 模式和负载选择,而不是统一使用同一个 N:Classic CAN 单帧最多 8B,常规电机控制、CANopen/CiA402 和少量 classic CAN 收发建议从 N=3 起步;CAN FD 单帧最多 64B,四通道或存在突发时建议从 N=8 起步。N=1/N=2 适合验证最小 PDO 能力、单通道低速诊断或少量 classic CAN。最大值为 N=24,即 3072B/方向。
5.3 SII/EEPROM SyncManager 要求
当前产品 EEPROM/SII 应保持大 PDO 单缓冲布局:
主站实际使用的 PDO 长度由 0x1C12/0x1C13 assignment 选择前 N 个 chunk 决定,并必须与 0x8010/0x8011 的 active profile 保持一致。
5.4 不使用 IgH:第三方 EtherCAT 主站配置 PDO
如果客户不使用 IgH 示例包 demo,而是使用 TwinCAT、CODESYS、Acontis 或自研 EtherCAT 主站,需要在主站工程中显式完成 PDO assignment、PDO profile apply 和 MCAN 通道配置。IgH 示例包 demo 中的自动配置,本质上对应下面的通用 CoE 配置流程。
5.4.1 选择 PDO 大小
ECAN-Lite 的 PDO 长度由 128B chunk 数量 N 决定:
text Copy ActivePDOBytes = 128 * N
N = 1..24主站必须为两个方向分别选择前 N 个 chunk:
示例:选择 N=3,即 SM2/SM3 均为 384B:
text Copy 0x1C12:00 = 0
0x1C12:01 = 0x1600
0x1C12:02 = 0x1601
0x1C12:03 = 0x1602
0x1C12:00 = 3
0x1C13:00 = 0
0x1C13:01 = 0x1A00
0x1C13:02 = 0x1A01
0x1C13:03 = 0x1A02
0x1C13:00 = 3示例:选择 N=8,即 SM2/SM3 均为 1024B:
text Copy 0x1C12:00 = 0
0x1C12:01..08 = 0x1600..0x1607
0x1C12:00 = 8
0x1C13:00 = 0
0x1C13:01..08 = 0x1A00..0x1A07
0x1C13:00 = 8这里的 01..08 和 0x1600..0x1607 / 0x1A00..0x1A07 表示连续范围,不是跳选;等价于逐项写入 :01 到 :08 的 8 个 assignment 子项。
主站工程中的 SM2/SM3 过程数据长度应等于 128 * N。如果主站导入 ESI 后需要手动选择 PDO,请确保选择的是连续的前 N 个 chunk,不要跳选或重排 chunk。
5.4.2 应用固件 PDO profile
0x1C12/0x1C13 决定主站实际映射长度;0x8010/0x8011 决定固件内部 active profile。两边必须一致,否则固件会拒绝应用或继续保持旧 profile。
推荐 startup SDO 顺序:
text Copy 1. 从站保持在 INIT/PREOP/SAFEOP,不要在 OP 中修改 PDO 大小
2. 配置 0x1C12/0x1C13,选择前 N 个 chunk
3. 写 0x8010:03 = N
4. 写 0x8011:03 = N
5. 写 0x8010:04 = tx_channel_mask
6. 写 0x8011:04 = rx_channel_mask
7. 写 0x8010:01 = 1,应用 TxPDO profile
8. 写 0x8011:01 = 1,应用 RxPDO profile
9. 读取 0x8010/0x8011 的 active readback,确认长度和 layout
10. 配置 0x8001..0x8004 MCAN 通道参数并 apply
11. 进入 OP,运行期通过 PDO 收发 CAN/CAN FD 帧active readback 建议至少检查:
5.4.3 完整初始化流程示例:不使用 IgH / 第三方主站
本节给出一套可以直接移植到 TwinCAT Startup SDO、CODESYS 启动参数、Acontis 或自研主站的配置流程。示例目标为:
如果只做保守 bring-up,建议把 N 改为 3,把 channel mask 改为 0x01,只启用 CAN0;若需要验证最小 PDO 能力,可使用 N=1。
Option flags 是 0x8010:07 (0x07) 和 0x8011:07 (0x07) 的按位配置值。常用值如下,完整 bit 表见第 9.1 节:
阶段 A:读取设备能力,决定主站配置上限。
阶段 B:配置 EtherCAT PDO assignment。主站在 PREOP/SAFEOP 阶段写入,选择连续前 N 个 PDO chunk。
0x1C12:01..08 = 0x1600..0x1607 表示连续写入 8 个子项,不是一次写范围。若 N=3,则只写 :01=0x1600、:02=0x1601、:03=0x1602,最后 :00=3;TxPDO 同理写 0x1A00..0x1A02。
阶段 C:配置固件 PDO profile。0x8010 控制 TxPDO/SM3 上传方向,0x8011 控制 RxPDO/SM2 下发方向。两边都要配置,且 PDO size multiplier 必须与阶段 B 的 assignment 数量一致。
如果需要 4 字节对齐,把 0x8010:07 (0x07) 或 0x8011:07 (0x07) 写成 0x02 后再 apply;如果需要 TxPDO 发送结果包,把 0x8010:07 (0x07) bit0 置 1。
阶段 D:读取 profile 回显,确认固件已经按主站期望生效。
示例中 active profile word 计算如下:
text Copy bits 0..4 = N - 1 = 7
bits 5..12 = channel_mask = 0x0F
bits 13..18 = profile = 0
bits 19..20 = budget = 0
bits 21..28 = option_flags = 0
ActiveProfileWord = 7 | (0x0F << 5) = 0x000001E7因此上表 D7/D8 应按实际计算值检查:N=8, mask=0x0F, profile=0, budget=0, options=0 时为 0x000001E7。如果启用 ALIGN4,OptionFlags=0x02,active profile word 会额外包含 (0x02 << 21)。
阶段 E:配置 MCAN 通道。下面示例把 CAN0 配成 CAN FD ISO,仲裁段 1Mbps,数据段 5Mbps,并使用 64B CAN FD Message RAM 布局。示例假设对端 CAN/CAN FD 设备的仲裁段和数据段采样点均为 87.5%,因此把采样点范围收敛为 875..875。CAN1..CAN3 分别使用 0x8002、0x8003、0x8004,子项完全相同。下表 SDO 冒号后的子项按十进制 SI 书写,并在括号中同步给出十六进制 SI;若主站软件使用十六进制显示,可以直接使用括号中的值。
0x8001:21..24 不是为某个波特率指定固定采样点,而是用于约束自动位时序求解器,使本设备的采样点与对端 CAN/CAN FD 设备一致。若已知对端采样点,建议把 min 和 max 都写成对端目标值,例如对端仲裁段 80.0%、数据段 87.5% 时,写 0x8001:21=800、0x8001:22=800、0x8001:23=875、0x8001:24=875。若对端采样点未知,应先参考对端驱动、工具或设备手册的推荐值,再通过错误计数和闭环收发验证。不建议在 CAN FD+BRS 的最终配置中保留过宽采样点范围,因为自动求解器可能选择一个合法但与对端不够匹配的时序。
若只启用 CAN0,仍建议只配置 0x8001,并把 0x8010/0x8011:04 写成 0x01。若使用 classic CAN,可把 0x8001:15=0,0x8001:20/23/24/33/34 保持默认或不写,并把 0x8001:65/66/68/72 设为 0(8B)以节省 Message RAM。
阶段 F:进入 OP 后,主站周期性写 RxPDO/SM2、读 TxPDO/SM3。若从站无法进入 OP,先检查阶段 B 的 SM2/SM3 长度和 assignment 数量;若进入 OP 但 CAN 不发送,优先检查阶段 C/E 的 channel mask 和通道 apply 状态。
5.4.4 PDO 打包与过程数据写入
主站最终操作的是 EtherCAT 过程数据中的连续 PDO buffer。以 N=8 为例:
一般主站程序操作的是 master process image 中的 RxPDO/TxPDO 起始指针,而不是直接写 ESC 物理地址。若调试工具直接暴露 ESC DPRAM 地址,则 RxPDO 固定头部位于 0x1100 + 0,RxPDO 第一帧位于 0x1100 + 24;TxPDO 固定头部位于 0x1D00 + 0,TxPDO 第一帧位于 0x1D00 + 24。
如果使用 TwinCAT/CODESYS,工具可能把过程数据拆成多个 STRING(16) 变量;应用需要先按第 5.1.1 节拼成连续 buffer,再按下面的 offset 写入或解析。若主站提供连续 PDO 指针,则直接对该指针操作。
连续 PDO buffer 的通用布局如下。24B 固定头部只负责描述本周期的帧区状态;真正的 CAN_FRAME / TX_RESULT 包都从 offset 24 开始连续排列。
5.4.4.1 从零构建一帧 RxPDO 下发数据
下面以“主站通过 RxPDO/SM2 让 ECAN-Lite 的 CAN0 发送一帧标准 classic CAN 数据帧”为例。阅读顺序按实际写入动作组织:先写帧封装区,再计算本周期 payload,最后填写 24B 固定头部并提交。
本例假设 PDO 已配置为 N=8,RxPDO active channel mask 为 0x0F,未开启 TX_RESULT、ALIGN4 和预约时间戳。
第一步:在 offset 24 写入 CAN_FRAME。
控制字 bit 组合:
text Copy ctrl = channel
| (dlc << 3)
| (ide << 7)
| (fdf << 8)
| (brs << 9)
| (x << 10)
| (tsf << 11)
| (kind << 13)本例中:
text Copy channel = 0
dlc = 8
ide = 0
fdf = 0
brs = 0
x = 0
tsf = 0
kind = 0
ctrl = 0x0040
StdIdField = 0x0123
raw_packet_bytes = 2 + 2 + 8 = 12因此 offset 24 开始的字节为:
text Copy 40 00 23 01 11 22 33 44 55 66 77 88第二步:计算本周期 payload 信息。
CRC-16/CCITT-FALSE 参数为 poly=0x1021、init=0xFFFF、xorout=0x0000、不反射输入输出。
第三步:填写 24B 固定头部。主站下发 RxPDO 时,头部字段按下表写入;其中 seq_end 必须最后写。
layout_id 推荐计算方式:
text Copy layout_word = ((N - 1) & 0x1F)
| ((channel_mask & 0xFF) << 5)
| ((profile & 0x3F) << 13)
| ((budget & 0x03) << 19)
| ((option_flags & 0xFF) << 21)
layout_id = (layout_word ^ (layout_word >> 16)) & 0xFFFF第四步:按提交顺序写入,避免从站读到半包。
text Copy 1. 清零 RxPDO buffer,或至少清零未使用帧区。
2. 从 offset 24 开始写入所有 CAN_FRAME 包。
3. 计算 payload_len、frame_count 和 payload_crc16。
4. 写固定头部 offset 0..3、6..23。
5. 最后写 offset 4..5 的 seq_end,且 seq_end == seq_begin。多帧打包时只重复第一步中的 CAN_FRAME 包:第一帧写在 offset 24,第二帧紧跟第一帧的 packet_bytes 后面,依次排列;payload_len 等于所有包长之和,frame_count 等于包数量。如果开启 ALIGN4,每个包的下一帧 offset 使用 align4(raw_packet_bytes) 前进,补齐字节必须为 0 并计入 payload_len。
TxPDO 读取时按相反方向处理:
从 SM3/TxPDO 连续 buffer 的 offset 0 读取 24B 固定头部。
判断 seq_begin == seq_end、crc_alg == 1、payload_len <= ActiveFrameAreaBytes。
计算 offset [24, 24 + payload_len) 的 CRC16 并与 payload_crc16 比较。
从 offset 24 开始按 CAN_FRAME 包长逐包解析。
如果启用 ALIGN4,下一包 offset 使用 align4(raw_packet_bytes) 前进。
若 overflow_sat != 0 或 STREAM_TRUNCATED=1,本周期 TxPDO 数据可能不完整。
5.4.5 第三方主站常见配置方式
如果主站不支持在线修改 PDO mapping,应在工程配置阶段固定 N,并避免运行中切换 PDO 大小。运行期只更新 SM2/RxPDO 输出数据、读取 SM3/TxPDO 输入数据。
5.4.6 配置错误快速判断
到这里为止,第 5 章已经说明了主站如何选择 PDO 大小、如何让固件应用 profile,以及如何写入一帧最小 RxPDO 数据。第 6..12 章开始拆解这些字节的正式协议定义:先讲 24B 固定头部,再讲通道状态、帧封装包、方向选项、TX_RESULT、CRC 和多通道预算。已经使用官方 IgH API 的读者可以快速浏览;需要自研解析库的读者应逐节实现。
6. PDO 固定头部
TxPDO 和 RxPDO 共用同一个 24B 固定头部。头部采用 little-endian 字段,ver_ihl 的高 4 bit 为 header version,低 4 bit 为 4B word 数;当前版本为 1,ihl=6,因此帧封装区从 offset 24 开始。
固定头部不是 SDO 对象,没有 RO/RW 属性;它的主站访问方向跟随 PDO 方向:RxPDO 头部由主站写入并由从站解析,TxPDO 头部由从站写入并由主站解析。
发布规则:发送端先构建完整帧封装区和头部字段,最后写 seq_end = seq_begin;接收端只有在 seq_begin == seq_end、payload_len <= ActiveFrameAreaBytes、crc_alg=1 且 CRC 校验通过时才解析 payload。该设计用于避免主站或从站读到半更新 PDO。
6.1 关键字段解释与接收判断
seq_begin、seq_end、layout_id、crc_alg、overflow_sat 不是需要主站单独 SDO 配置的参数,它们是每个 PDO 周期中固定头部携带的运行态字段。主站在 RxPDO 下发方向需要按规则写入它们;主站在 TxPDO 上传方向需要按规则检查它们。
说明:
layout_id 是 PDO 头部中的短标识,便于主站快速判断“当前 PDO 布局是否变过”。完整配置回显应读取 0x8010/0x8011:12 Active profile word 和 :11 Active layout CRC。
文档或调试口径中如果出现 overflow_set,对应的是本头部字段 overflow_sat:它不是一个开关,而是“本周期发生溢出/截断后的饱和计数”。
payload_crc16 的计算范围是帧封装区,即 PDO offset [24, 24 + payload_len),不包含 24B 固定头部。
payload_len 是本周期实际有效帧封装字节数,不是 PDO 总长度。未使用的帧区必须填 0。
接收端推荐判断顺序:
text Copy 1. 读取固定头部 A。
2. 检查 seq_begin == seq_end;不相等则忽略本周期 PDO。
3. 检查 crc_alg == 1。
4. 检查 payload_len <= ActiveFrameAreaBytes。
5. 对 offset 24 开始的 payload_len 字节计算 CRC-16/CCITT-FALSE。
6. 再读取固定头部 B;若 A 与 B 关键字段不一致,说明读期间 PDO 被更新,忽略本周期。
7. 解析 CAN_FRAME / TX_RESULT。
8. 若 overflow_sat != 0 或 STREAM_TRUNCATED=1,将本周期标记为数据不完整。配置示例:主站希望 TxPDO/RxPDO 都使用 N=8、CAN0..CAN3、profile 0、Balanced、不开启方向选项时:
text Copy 0x1C12 / 0x1C13: 选择前 8 个 128B chunk
0x8010:03 = 8 TxPDO PDO size multiplier
0x8010:04 = 0x0F TxPDO channel mask
0x8010:05 = 0 TxPDO profile 0
0x8010:06 = 0 TxPDO Balanced budget
0x8010:07 = 0x00 TxPDO option flags
0x8010:01 = 1 apply TxPDO profile
0x8011:03 = 8 RxPDO PDO size multiplier
0x8011:04 = 0x0F RxPDO channel mask
0x8011:05 = 0 RxPDO profile 0
0x8011:06 = 0 RxPDO Balanced budget
0x8011:07 = 0x00 RxPDO option flags
0x8011:01 = 1 apply RxPDO profileapply 后读取 0x8010/0x8011:09..12。如果 Active PDO bytes、Active frame area bytes、Active layout CRC、Active profile word 与预期一致,后续 PDO 头部中的 layout_id 应保持稳定。
header_flags:
7. 通道状态字
每路通道状态压缩为 16bit,固定放在 PDO 头部。PDO 只承载快速状态,详细原因通过 SDO 读取。
当 warn/bus_off/rx_pressure/tx_pressure/detail_pending 置位时,主站应读取 0x9000..0x9003 获取详细寄存器和计数快照。若错误来自 PDO 封装层,应读取 0x8010/0x8011 的 LastPDOError / PDOErrorCounter / PDOOverflowCounter。
8. 帧封装包
每个帧封装包从 2B 控制字开始,控制字决定后续 CAN ID、时间戳和 data 的长度。
帧封装包跟随 PDO 方向:RxPDO 中的 CAN_FRAME 是主站请求从站发送到 CAN 总线;TxPDO 中的 CAN_FRAME 是从站从 CAN 总线收到后上传给主站;TxPDO 中的 TX_RESULT 是从站对 RxPDO 下发帧的发送结果回传。
除特别说明外,PDO 固定头部、帧封装包、TX_RESULT 和 SDO 中的多字节数值均使用 little-endian。主站侧不要按主机字节序直接强转未对齐结构体,建议按字节流显式读取。
text Copy Byte0:
bit0..2 CH CAN channel id,当前使用 0..3
bit3..6 DLC 原始 CAN DLC,0..15
bit7 IDE 0=11bit standard id,1=29bit extended id
Byte1:
bit0 FDF 0=classic CAN,1=CAN FD
bit1 BRS CAN FD bit rate switch
bit2 X FDF=0 时为 RTR,FDF=1 时为 ESI
bit3..4 TSF 0=no timestamp,1=delta16,2=delta32,3=full64
bit5..6 KIND 0=CAN_FRAME,1=TX_RESULT,2=STREAM_META,3=reserved
bit7 D64 0=data length by DLC,1=fixed 64B data window当前主流程使用 KIND=0 CAN_FRAME。KIND=1 TX_RESULT 由 TxPDO 可选生成。KIND=2 STREAM_META 保留给 whole-stream CRC 等扩展能力。KIND=3 当前必须视为非法。
8.1 CAN_FRAME 格式
text Copy Standard ID:
Ctrl[2] + StdIdField[2] + Timestamp[0/2/4/8] + Data[0..64] + Padding
Extended ID:
Ctrl[2] + ExtIdField[4] + Timestamp[0/2/4/8] + Data[0..64] + PaddingStdIdField:
ExtIdField:
ID_AUX 建议语义:
未使用时发送端必须写 0,接收端忽略。
8.2 DLC 与数据长度
classic CAN 中 DLC<=8、BRS=0、D64=0。若 FDF=0 && X=1,该帧为 RTR,data length 必须为 0。CAN FD 中 X 表示 ESI,不存在 RTR。
8.3 包长度计算
text Copy id_bytes = IDE ? 4 : 2
ts_bytes = TSF == 0 ? 0 : (TSF == 1 ? 2 : (TSF == 2 ? 4 : 8))
data_bytes = (FDF == 0 && X == 1) ? 0 :
(D64 ? 64 : can_dlc_to_len(DLC))
raw_packet_bytes = 2 + id_bytes + ts_bytes + data_bytes
packet_bytes = ALIGN_4_ENABLE ? align4(raw_packet_bytes) : raw_packet_bytes未使用帧区必须填 0。若开启 4 字节对齐,padding 字节必须为 0 并计入 payload_len。
8.3.1 开启 4 字节对齐
4 字节对齐由方向选项 ALIGN_4_ENABLE 控制,不是 0xF000 只读能力对象直接开启。0xF000:15 (0x0F) 用于确认设备是否声明支持该能力;真正的开关在 0x8010/0x8011:07 (0x07) Option flags bit1。
开启步骤:
text Copy 1. 读取 0xF000:15,确认 bit1 ALIGN4 option mask 为 1。
也可读取 0xF000:16,确认 bit5 ALIGN4 feature 为 1。
2. 在 PREOP/SAFEOP 中写入 0x8010/0x8011 requested profile。
3. 将目标方向的 0x8010:07 或 0x8011:07 bit1 置 1。
4. 写 0x8010:01 = 1 或 0x8011:01 = 1 apply。
5. 读取 0x8010/0x8011:02,确认 Status = 0。
6. 读取 0x8010/0x8011:12,确认 Active profile word 中 OptionFlags 的 bit1 已生效。示例:保持其他方向选项不变,只打开 RxPDO 4 字节对齐:
text Copy old = read_u8(0x8011:07)
write_u8(0x8011:07, old | 0x02)
write_u8(0x8011:01, 1)
check read_u8(0x8011:02) == 0示例:关闭 TxPDO 4 字节对齐:
text Copy old = read_u8(0x8010:07)
write_u8(0x8010:07, old & ~0x02)
write_u8(0x8010:01, 1)
check read_u8(0x8010:02) == 0开启后,发送端必须把每个帧包补齐到 4 字节边界,padding 字节必须写 0,并且 padding 字节计入固定头部 payload_len。接收端解析下一包时也必须使用对齐后的 packet_bytes,不能只按原始 CAN 数据长度前进。
长度示例:
8.4 时间戳字段
TSF 决定 CAN_FRAME 中是否携带时间戳字段。普通 TxPDO 上传方向中,时间戳用于描述从站接收 CAN 帧的时间;RxPDO 下发方向中,TSF_NONE 表示立即发送,TSF_FULL64 可被预约发送格式复用。
TxPDO 中同一 Packet sequence 内的 delta16/delta32 以该周期首个可用时间基准为参考。主站用于排序和诊断时应按无符号差值处理 wrap。若主站不需要时间戳,建议使用 profile 0/4,减少每帧开销。
RxPDO 预约发送只使用 TSF_FULL64 的 8B 字段,并要求格式如下:
text Copy format:u8 = 1
flags:u8 = 0
tag:u16
offset_ns:u32offset_ns 表示相对下一次 SYNC0 周期起点的目标相位。该格式不是绝对时间戳;如果目标相位已经错过,固件不会把帧延迟到下一个周期补发,主站应预留足够相位余量。
9. 封装 Profile 与方向选项
0x8010 控制 TxPDO profile,0x8011 控制 RxPDO profile。当前出厂支持以下 profile:
方向选项由 0x8010/0x8011:07 Option flags 控制。0x8010 作用于 TxPDO/SM3/Input 上传方向,0x8011 作用于 RxPDO/SM2/Output 下发方向。
9.1 Option flags bit 表
Option flags 是一个 8 bit 位图。主站写 requested value 后,必须再写 0x8010:01=1 或 0x8011:01=1 apply,读取 0x8010/0x8011:02=0 和 :12 Active profile word 才表示真正生效。
常用写入值:
能力判断:
当前能力掩码以 0xF000 为准。主站应先读取能力对象,再选择 profile 和 option flags。
9.2 不配置时的默认开关状态
如果主站不写 0x8010/0x8011 的 profile 相关 SDO,设备对象字典中的 requested 默认值如下。注意:0xF000 表示“支持能力”,不表示默认启用;真正启用状态由 0x8010/0x8011 的 requested profile 和 apply 后的 active readback 决定。
推荐主站不要依赖“隐式默认已经生效”的假设。启动时应显式配置 0x1C12/0x1C13、写入 0x8010/0x8011:03..07,再写 0x8010/0x8011:01=1 apply,并读取 :09..12 确认 active 状态。
10. TX_RESULT
TX_RESULT 是可选帧包,用于在 TxPDO 中回传 RxPDO 下发帧的发送结果。
text Copy TX_RESULT:
Ctrl[2] + RefPacketSeq[2] + RefFrameIndex[1] + ResultCode[1]Ctrl 的 KIND=1,CH 表示结果对应的 CAN 通道。RefPacketSeq 对应主站下发 RxPDO 固定头部中的发布序号,也就是 seq_begin == seq_end 后提交的那个序号;RefFrameIndex 对应该 RxPDO payload 中解析到的第几个 KIND=0 CAN_FRAME,从 0 开始计数。这样主站可以把 TX_RESULT 和原始下发帧建立一一对应关系。
ResultCode:
TX_RESULT 只表示从站把该帧交给 MCAN 发送路径的结果,不等价于目标 CAN 节点已经完成业务处理。若使用 TX FIFO/Queue,queued 表示已经进入本地发送队列,实际总线发送仍受仲裁、bus off、TX FIFO 空间影响。
如果主站不需要逐帧 ACK,可关闭 TX_RESULT,只通过 PDO 头部通道状态和 SDO 计数器观察拥塞。
11. CRC 与完整性策略
默认不为每个 CAN_FRAME 添加 CRC32。
原因:
CAN/CAN FD 总线本身已有 CAN CRC。
EtherCAT 帧已有链路 FCS 和 working counter。
per-frame CRC32 会增加 4B/帧,classic 8B 标准帧开销从 12B 增加到 16B,约 33%。
逐帧 CRC32 会增加 1ms 周期中的小包计算抖动。
默认使用 ActiveLayoutCrc 校验 PDO layout 合约,该 CRC 只在 profile apply 时计算。运行期每个 PDO 周期使用固定头部中的 payload_crc16 保护 FramePacketStream,算法为 CRC-16/CCITT-FALSE;它用于识别半更新或错误 payload,不是 CAN 帧级业务 CRC。若未来确实需要运行期额外完整性检查,应使用能力位声明的 STREAM_CRC32_ENABLE,并以 STREAM_META 包承载 whole-stream CRC32,而不是给每个 CAN_FRAME 加 CRC。
12. 多通道共享预算
PDO 不再给每路 CAN 固定槽位。调度器按帧区字节预算工作:
text Copy frame_area = ActivePDOBytes - 24
reserved_bytes = enabled_channel_count * policy_reserved_bytes
shared_bytes = frame_area - reserved_bytes预算策略:
一条 CAN_FRAME 必须整体放入本周期帧区,不允许跨周期拆分。如果空间不足,设备设置 STREAM_TRUNCATED,增加 overflow_sat 和 SDO PDOOverflowCounter。
13. SDO 对象字典
前面的章节描述周期 PDO 数据,也就是 OP 运行后每个 EtherCAT 周期会交换的字节。SDO 对象字典是配置和诊断入口:进入 OP 前用它设置 PDO profile 和 MCAN 参数,运行中用它读取能力、错误计数和详细状态。读者如果只需要查对象,可以直接从本章按对象号定位;如果正在做 bring-up,建议先看 13.1、13.2、13.4、13.8。
本章所有 SDO 子项表均给出“类型”列。类型采用 EtherCAT CoE 常用标记:U8 为 unsigned 8 bit,U16 为 unsigned 16 bit,U32 为 unsigned 32 bit;若后续出现有符号 32 bit,可标为 D32/I32。当前 ECAN-Lite 对象字典主要使用 U8/U16/U32。
13.1 对象总览
13.2 0x8010/0x8011 PDO Profile Control
0x8010 控制 TxPDO/Input 方向,数据流为 S2M;0x8011 控制 RxPDO/Output 方向,数据流为 M2S。SI1/3/4/5/6/7/8 为主站写入的 requested 配置或命令,SI2/9..16 为从站返回的状态和 active readback。
Status 常用值:
Active profile word 打包格式:
Command 位定义:
Last PDO error 常用值:
PDO error counter 统计解析、CRC、非法字段等封装层错误;PDO overflow counter 统计本周期帧区不足、TX/RX 背压导致的溢出或丢弃。现场排查时先看 Status,再看 LastPDOError 和两个计数器是否持续增加。
13.2.1 0x8020 Data Path Global Control
0x8020 是数据面全局控制对象。它不改变 EtherCAT SM/PDO 映射长度,主要用于运行期兼容策略、诊断开关和服务预算。写入后通过 Apply command=1 生效,Apply status=0 表示接受。
13.2.2 0x8021..0x8024 MCAN Data Path Control
0x8021..0x8024 分别对应 MCAN0..MCAN3。该对象把每路 MCAN 的数据面策略从 legacy policy word 拆成独立字段,便于产品界面、脚本和客户主站做精确配置。它不改变 MCAN 位时序、过滤器或 Message RAM;这些仍由 0x8001..0x8004 管理。
RX budget policy:
RX cache depth:
RX overflow policy:
Critical frame policy:
TX overflow policy:
Bus-off recovery policy:
Active control word 打包格式:
13.2.3 0x8030 PDO Diagnostic Test Control
0x8030 是研发和现场性能定位对象,不建议客户产品长期打开。除写 0 外,修改测试策略前必须先写 Test enable key = 0x4543414E(ASCII ECAN)。如果 key 为 0,所有测试策略也必须为 0,否则写入会被拒绝。
TxPDO bypass flags:
RxPDO bypass flags:
Legal combination mask:
0x9011 用于观察周期稳定性和固件热路径耗时。除 Clear command 外均为只读。周期数单位是 CPU cycle,换算时间时可用 0x8000:4 CPU clock hz。
13.2.5 0x9020..0x9023 MCAN Data Path Diagnostics
0x9020..0x9023 分别对应 MCAN0..MCAN3。它们用于把 0x8021..0x8024 的策略执行结果可视化,帮助判断问题来自 CAN 侧输入过多、PDO 空间不足、TX FIFO 背压、bus-off 还是服务预算过小。
13.3 0x8000 System Config
CAN pin rotation 只允许在芯片/板级固定 CAN 引脚组之间旋转逻辑通道,不提供任意 GPIO 复用配置。
13.4 0x8001..0x8004 MCAN Channel Config
每路通道结构相同,0x8001 对应 CAN0,0x8004 对应 CAN3。
对象完整子项按功能分组如下。普通客户通常只需要配置 SI15/16/19/20 和必要的 FIFO/Queue 参数;滤波器、TSU、Timeout 属于高级配置。
通道命令与状态:
Node mode 取值:
手动 bit timing 仅在 SI7 Bit timing mode = 1 时生效。自动模式下主站配置 Nominal/Data bitrate 和采样点范围,固件根据 MCAN 源时钟求解 BRP/TSEG/SJW。采样点范围应按对端设备配置:已知对端采样点时建议把 min/max 都写成目标采样点;未知时先按对端文档推荐值配置并验证收发质量。手动模式下使用 SI25..32。
滤波器全局字段:
滤波器编辑窗口:
Entry cmd:
Entry status:
典型过滤器配置流程:
读取 Std list max / Ext list max,确认容量。
写 Std filter count 或 Ext filter count。
写 current index。
写 filter type/action/sync/id1/id2。
写 entry cmd = 2 保存当前索引。
重复配置多个条目。
写 Apply command = 1 让通道配置生效。
如需掉电保存,写 Flash command bit0 = 1。
RAM/FIFO/Buffer 字段:
注意:表中的 SI 是十进制子项号;很多主站界面会用十六进制显示。用户常说的 0x41/0x42/0x44 分别就是十进制 65/66/68,对应 RX FIFO0、RX FIFO1、RX Buffer 的元素数据区大小。它们只决定 MCAN Message RAM 里每个元素可容纳的最大数据字节数,不决定 PDO 中单帧 CAN FD 的 DLC;实际 DLC 仍由 RxPDO/TxPDO 帧包里的 DLC 字段决定。
data size 使用 HPM MCAN 驱动枚举,不是字节数本身。常用枚举如下:
Message RAM 预算由元素数量和 data size 共同决定。CAN FD 通用默认建议 RXFIFO0=48, RXFIFO1=12, RXBUF=12, TXFIFO=32, TXBUF=0, TXEVENT=32, data size=7;classic CAN 可把 data size 降到 0,以节省 RAM 给更多元素。配置非法或超过通道 Message RAM 预算时,Apply status 会返回错误,运行配置不会切换到新值。
Timestamp/TSU/Timeout 字段:
TDC 策略:
CAN FD 默认 TDC enable=1。
数据段低于 5M 时,主站可通过 SDO 关闭 TDC。
数据段达到 5M 及以上时,固件忽略 TDC enable=0 并强制开启 TDC。
TDC offset/filter 默认 0,表示由 HPM MCAN 驱动按实际数据段时序自动计算。
非 0 的 TDC offset/filter 仍被固件保留并下发给 MCAN 驱动,供现场专家调试使用。
手动覆盖时建议 offset/filter 成对配置。
该对象为 RO,方向为 S2M,用于主站按需读取通道详细状态。
13.6 0xA000..0xA003 MCAN Register Service
0xA000..0xA003 分别对应 MCAN0..MCAN3 的寄存器访问服务。该对象用于现场诊断和专家调试,不建议普通应用周期性访问。写寄存器会受白名单保护,避免误写关键地址导致总线异常。
Status:
写白名单偏移:
读寄存器流程:
写 Offset。
写 Command = 1。
读取 Status,为 0 时读取 Read value。
写寄存器流程:
确认设备处于允许调试访问的状态。
写 Offset 和 Write value。
写 Command = 2。
读取 Status,若为 2 表示该寄存器只允许读或不建议通过 SDO 写。
13.7 0xB000 Device Maintenance
Access mode request/status:
Maintenance command 是 bit mask。bit0..4 是传统维护命令;bit5/bit6 是独立命令,写入时必须单独写该 bit,不能与其他 bit 合并。
Legacy maintenance diag flags:
Maintenance status 常用值:
维护命令完成后 Maintenance sequence 增加。主站执行维护命令时,应先记录旧 sequence,写命令后轮询 sequence 变化和 status。
13.8 0xF000 Device Objects
主站必须读取 0xF000 能力对象后再选择 PDO profile。
该对象为 RO,方向为 S2M,用于主站识别设备能力、版本和协议上限。
PDO 能力与上限:
Encapsulation profile mask:
PDO option flags mask:
PDO feature flags:
Device service flags:
RxPDO 预约发送复用动态帧 TSF_FULL64 字段,不改变普通 CAN frame 包结构:
text Copy format:u8 = 1
flags:u8 = 0
tag:u16
offset_ns:u32TSF_NONE 仍为立即发送;TSF_FULL64 format=1 表示预约到下一次 SYNC0 周期的 offset_ns 相位发送。同一相位按 PDO 帧顺序排队。
预约发送实现约束:
主站必须先确认 0xF000:16 (0x10) 中的 RxPDO TSF 预约发送能力位。
offset_ns 以当前 EtherCAT DC/SYNC0 周期为参考,推荐先使用 100000ns 或更大的保守相位做 bring-up。
设备按 SYNC0 相位调度预约帧;已超过目标相位的帧不会跨周期补发,主站应预留足够的 offset_ns 余量。
预约发送与直接发送共用 CAN 发送路径;当通道拥塞或发送异常时,通过 PDO 状态和 SDO 诊断计数反馈。
当主站停止后,ESC 过程数据区可能保持最后一帧 RxPDO 镜像;固件将完全相同的重复镜像作为幂等 no-op,不记为真实解析错误。
13.9 预约发送与直接发送实时性对比
预约发送效果依赖主站周期本身的确定性。若主站应用使用普通 usleep() 相对延时,1ms/2ms 周期会累积应用执行时间和 Linux 唤醒抖动,CAN 侧抓包会出现长尾。IgH 示例 igh_mcan_gateway_tx_probe 已改为绝对时间周期,并支持:
text Copy --rt-priority 80 --spin-us 100其中 --rt-priority 将周期线程设为 SCHED_FIFO,--spin-us 表示睡眠到 deadline 前 N 微秒后短自旋对齐目标时间。示例结束时会输出 master_period,应先确认主站周期稳定,再评估 CAN 侧实时性。
以下数据来自实验室参考测试:Linux IgH 物理主机,ECAN-Lite 单从站单 MCAN 通道接 CAN 分析仪,PDO=3 即 384B,CAN FD+BRS,payload 16B,发送 1000 帧,CAN 分析仪保存前 1200 帧时间戳。
结论:直接发送适合普通功能测试,CAN 发送时刻会跟随 PDO 到达和固件处理时刻;当主站周期收敛后,预约 100us 能把 CAN 释放相位稳定到 SYNC0 后固定窗口。需要稳定实时输出时,建议使用预约发送,并同时记录主站 master_period 和 CAN 分析仪时间戳。
14. 配置流程
14.1 推荐启动流程
主站进入 PREOP/SAFEOP。
读取 0xF000 能力对象。
配置 0x1C12/0x1C13,选择前 N 个 128B chunk。
写 0x8010/0x8011 requested profile。
写 0x8010:1 = 1、0x8011:1 = 1 应用 profile。
读取 ActivePDOBytes / ActiveFrameAreaBytes / ActiveLayoutCrc / ActiveProfileWord。
对每个启用通道写 0x8001..0x8004 CAN 参数并 Apply command=1。
进入 OP。
OP 中只通过 PDO 收发数据;遇到错误再按需读取 SDO 详情。
14.2 切换 PDO 大小
PDO 大小影响 SM2/SM3 长度,必须在 INIT/PREOP/SAFEOP 完成。OP 中不允许改变 active PDO size、channel mask、profile、budget 或 option flags。
text Copy 1. 从 OP 退回 SAFEOP/PREOP
2. 修改 0x1C12/0x1C13 assignment chunk count
3. 写 0x8010/0x8011 PDO size multiplier
4. Apply profile
5. 校验 active readback
6. 重新进入 OP若 assignment chunk count 与 PdoSizeMultiplier 不一致,设备返回 Status=5 master mapping reload required,并保持旧 active profile。
14.3 CAN FD 5M 配置建议
text Copy FD enable = 1
Nominal bitrate= 1000000
Data bitrate = 5000000
TDC enable = 1
TDC offset = 0
TDC filter = 0
RX/TX data size= 64B
Apply command = 1IgH demo 默认对 CAN FD 通道写入 TDCEnable=1, TDCOffset=0, TDCFilter=0。5M 及以上即使主站写 TDCEnable=0,固件也会强制开启。
15. IgH 主站集成指导
IgH 主站示例包可直接复用 PDO 协议层,也可以运行 10 轴 CiA402 demo 做系统 bring-up。示例命令均以进入解压后的 IgH 示例包目录后的相对路径为准。
15.1 代码层级
IgH 示例包按职责拆成三层。客户应用通常只需要选择一个最高层入口,低层由库内部继续复用。
示例程序只用于 bring-up 和回归测试,不建议客户业务程序直接复制 demo 主函数。推荐复用库接口:
15.2 Linux 环境准备
推荐在物理 Linux 主机上运行 IgH。若使用虚拟机,只建议用于早期枚举和功能 bring-up;稳定周期和 DC 行为应以物理机结果为准。
基础依赖:
sh Copy sudo apt update
sudo apt install -y git build-essential cmake autoconf automake libtool \
pkg-config linux-headers-$(uname -r)IgH EtherCAT master 需要启用 generic 驱动和 hrtimer:
sh Copy git clone https://gitlab.com/etherlab.org/ethercat.git
cd ethercat
./bootstrap
./configure --prefix=../ethercat-install \
--sysconfdir=../ethercat-install/conf \
--enable-generic \
--enable-hrtimer
make -j$(nproc ) all modules
sudo make modules_install install
sudo depmod按 IgH 安装说明配置 EtherCAT 专用网口,例如将 master0 绑定到 enp4s0,并使用 generic 驱动模块。配置完成后重启 master 并确认从站可枚举:
sh Copy sudo systemctl restart ethercat
sudo ethercat slaves15.3 构建 IgH 示例包
基础构建命令:
sh Copy cmake -S . -B build
cmake --build build默认 ECAN_IGH_BUILD_DEMO=AUTO。如果 CMake 找到 ecrt.h 和 libethercat,会生成 libecan_mcan_host.a、libecan_igh_host.a、igh_simple_loop、igh_canopen_sdo_probe、igh_cia402_single_axis_demo 和 igh_cia402_10axis_demo;如果未找到 IgH 开发文件,则只构建 ecan_mcan_host 协议静态库,配置过程不会失败。
若使用本地 IgH 构建目录:
sh Copy cmake -S . -B build \
-DECRT_INCLUDE_DIR=../ethercat/include \
-DECRT_LIBRARY=../ethercat/lib/.libs/libethercat.so
cmake --build build -j$(nproc )如果只需要协议静态库,不构建 IgH demo:
sh Copy cmake -S . -B build -DECAN_IGH_BUILD_DEMO=OFF
cmake --build build如果需要强制构建 demo:
sh Copy cmake -S . -B build -DECAN_IGH_BUILD_DEMO=ON
cmake --build build15.3.1 使用 IgH FoE OTA 更新固件
ECAN-Lite 支持 EtherCAT FoE 写入打包后的应用固件。设备侧 FoE 目标文件名固定为 ecan_lite_app,密码默认为 0。主站使用 IgH 自带 ethercat 命令即可完成更新,不依赖本目录 demo。
准备条件:
更新前先读取当前版本:
sh Copy sudo /opt/etherlab/bin/ethercat upload -p 0 0x100A 0 --type string
sudo /opt/etherlab/bin/ethercat upload -p 0 0xF000 5 --type uint16
sudo /opt/etherlab/bin/ethercat upload -p 0 0xF000 6 --type uint16写入固件:
sh Copy sudo /opt/etherlab/bin/ethercat foe_write \
-p 0 \
-o ecan_lite_app \
/tmp/ecan_lite_v140494.bin上面命令中的 -p 0 是 FoE password,-o ecan_lite_app 是设备侧目标文件名。如果现场 IgH 工具版本对从站 position、password 或远端文件名使用不同选项,应以 ethercat foe_write --help 为准;核心参数保持不变:目标从站、password=0、远端文件名 ecan_lite_app、本地打包固件路径。
常见错误:
更新成功后,固件会写入空闲 APP 分区并请求复位。等待从站重新上线后,重新扫描并确认版本:
sh Copy sudo systemctl restart ethercat
sudo /opt/etherlab/bin/ethercat slaves
sudo /opt/etherlab/bin/ethercat upload -p 0 0x100A 0 --type string
sudo /opt/etherlab/bin/ethercat upload -p 0 0xF000 5 --type uint16
sudo /opt/etherlab/bin/ethercat upload -p 0 0xF000 6 --type uint1615.4 二次开发接口
二次开发时先选择抽象层,不要把全部函数都暴露给业务代码。完整说明见示例包内 API.md:
常规 CAN/CAN FD 网关应用优先使用 MCAN Port 层。业务代码应优先调用扁平接口 igh_mcan_port_send_can()、igh_mcan_port_send_canfd()、igh_mcan_port_schedule_can() 和 igh_mcan_port_receive(),不需要先构造 igh_mcan_tx_frame_t。这样调用链最短,用户数据只在写入 RxPDO 帧区时拷贝一次,同时 PDO header、CRC、帧边界、TxPDO 解析错误等细节仍由库封装:
c Copy igh_mcan_tx_frame_t tx;
igh_mcan_rx_frame_t rx[32 ];
size_t rx_count = 0 ;
uint8_t data[8 ] = {0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 };
igh_mcan_tx_frame_set_can(&tx, 0 , 0 , 0x123 , 0 , data, sizeof (data));
igh_mcan_port_exchange(&mcan, &tx, 1 , rx, 32 , &rx_count);需要周期实时控制时,推荐使用 igh_mcan_port_cycle_begin()、igh_mcan_port_receive()、igh_mcan_port_send_can/canfd()、igh_mcan_port_schedule_can/canfd()、igh_mcan_port_cycle_end() 组成固定周期。igh_mcan_tx_frame_set_*()、igh_mcan_port_send() 和 igh_mcan_port_exchange() 只保留给批量发送、bring-up、测试脚本或旧代码兼容。
最小 CAN 收发示例:
sh Copy sudo ./build/igh_simple_loopCANopen SDO 探测示例:
sh Copy sudo ./build/igh_canopen_sdo_probe \
--node 1 \
--index 0x1000 \
--sub 0 \
--bitrate 100000015.5 不使用 demo 的 IgH 集成流程
如果客户不运行 igh_simple_loop、igh_cia402_*_demo,而是在自己的主站程序中集成 ECAN-Lite,推荐仍复用 IgH 示例包中的三层接口。demo 只是一份可运行样例,真正需要移植到客户程序里的流程应拆成“主站配置、MCAN 通道配置、周期收发、业务协议处理”四部分。
15.5.1 推荐接入方式
常规项目优先选择 MCAN Port API。这样即使不使用 demo,也可以避免把 demo 的长流程复制到业务代码中。
15.5.2 从零配置一个 IgH 应用
步骤 1:扫描 EtherCAT 拓扑,确认 ECAN-Lite 的从站位置。
sh Copy sudo ethercat slaves步骤 2:选择 PDO 大小、周期和通道。首次调试建议从 1 个从站、1 个 MCAN 通道、cycle_us=10000 开始;classic CAN 或 CiA402/CANopen 电机场景从 pdo-n=3 起步,CAN FD 尤其是 64B 载荷或多通道突发场景从 pdo-n=8 起步;确认 OP 和 CAN 收发稳定后,再增加从站、通道和周期压力。
步骤 3:创建 IgH 通用配置。
c Copy ecan_igh_config_t igh_config;
ecan_igh_default_config(&igh_config);
ecan_igh_config_set_slave_count(&igh_config, 1 );
ecan_igh_config_set_cycle_us(&igh_config, 10000 );
ecan_igh_config_set_pdo_multiplier(&igh_config, 3 ); 多从站且 PDO 大小不同时,使用 ecan_igh_config_set_slave_pdo_multiplier() 分别配置。例如前两个从站使用 N=6,第三个从站只启用两路 MCAN 时可使用 N=3。
步骤 4:创建 MCAN 通道配置,并写入启动 SDO 队列。
c Copy igh_mcan_port_config_t mcan_config;
igh_mcan_port_default_config(&mcan_config);
igh_mcan_port_set_channel_mask(&mcan_config, 0 , 0x01 , 0x00 );
igh_mcan_port_set_classic_channel(&mcan_config, 0 , 0 , 1000000 );
igh_mcan_port_apply_config(&igh_config, &mcan_config);IgH 通用层会按 PDO 倍数注册前 N 个 PDO chunk,并配置 0x1C12/0x1C13。igh_mcan_port_apply_config() 会追加 ECAN-Lite 运行所需的启动 SDO,包括 0x8010/0x8011 的 PDO profile、通道掩码、PDO 长度,以及 0x8001..0x8004 的 MCAN 波特率和 CAN FD 参数。
步骤 5:初始化主站、MCAN Port,并等待从站进入 OP。
c Copy ecan_igh_context_t igh;
igh_mcan_port_t mcan;
ecan_igh_init(&igh, &igh_config);
igh_mcan_port_init(&mcan, &igh, &mcan_config);
ecan_igh_wait_op_timeout(&igh, 10000 );步骤 6:在应用周期中完成一次 EtherCAT/CAN 交换。
c Copy uint8_t data[8 ] = {0 };
igh_mcan_rx_frame_t rx[32 ];
size_t rx_count = 0 ;
igh_mcan_port_cycle_begin(&mcan);
igh_mcan_port_receive(&mcan, rx, 32 , &rx_count);
igh_mcan_port_send_can(&mcan, 0 , 0 , 0x123 , 0 , data, sizeof (data));
igh_mcan_port_cycle_end(&mcan);步骤 7:给周期线程增加实时配置。Linux 上建议至少设置 SCHED_FIFO、mlockall()、固定运行 CPU,并把 IgH 主服务和网卡中断放在规划好的 RT 核心上。周期可以先使用 5ms 或 2ms,稳定后再评估 1ms。
步骤 8:增加运行时检查。每个周期应监控 domain working counter、ecan_igh_domain_is_complete()、从站 OP 状态、MCAN Port 解析错误和 TxPDO header。出现 domain_complete=0 时不要继续推进运动目标,应保持上一周期输出或进入安全停发逻辑。
15.5.3 不使用 MCAN Port API 时的手动配置
Raw PDO 方式下,应用需要自行完成两类工作:
PDO 映射选择:按第 5 章规则,把 RxPDO/TxPDO 的 chunk 加入 0x1C12/0x1C13。每个 chunk 是 128B,pdo-n=N 表示选择 0x1600..0x160(N-1) 和 0x1A00..0x1A(N-1)。
ECAN-Lite 运行参数:写入 0x8010/0x8011 和 0x8001..0x8004。最小配置应包含通道掩码、PDO 长度、profile 和每个 MCAN 通道的 nominal/data bitrate。配置完成后,通过 0x8010:02 (0x02)、0x8011:02 (0x02) 或 0x9000 读取 active profile 和状态,确认固件已经按预期生效。
Raw PDO 周期交换时,使用以下接口拿到 buffer:
c Copy uint8_t *rxpdo = NULL ;
const uint8_t *txpdo = NULL ;
size_t rxpdo_size = 0 ;
size_t txpdo_size = 0 ;
ecan_igh_get_rxpdo_buffer(&igh, slave_index, &rxpdo, &rxpdo_size);
ecan_igh_get_txpdo_buffer(&igh, slave_index, &txpdo, &txpdo_size);rxpdo 是主站输出到 ECAN-Lite 的数据,txpdo 是 ECAN-Lite 返回给主站的数据。建议仍使用 igh_mcan_pdo_writer_* 和 igh_mcan_pdo_parse_frames_ex() 辅助封装/解析,避免客户应用重复实现 PDO header、CRC、offset 和帧边界处理。
15.5.4 不使用 CiA402 demo 控制电机
电机项目也不必直接运行 igh_cia402_single_axis_demo 或 igh_cia402_10axis_demo。客户应用可以复用协议层:
先按 15.5.2 完成 IgH 和 MCAN Port 初始化。
使用 igh_cia402_axis_init() 建立轴表,描述每个电机所在的从站、MCAN 通道、NodeID 和目标步进。
使用 igh_cia402_context_init() 绑定 MCAN Port 与轴表。
启动阶段调用 igh_cia402_send_nmt_all()、igh_cia402_configure_csp_all_timeout()、igh_cia402_request_actual_position_all_timeout()、igh_cia402_enable_all() 完成 NMT、CSP 映射、实际位置读取和 CiA402 使能。
运动周期中调用 igh_cia402_process_rx() 处理 TPDO/SDO/heartbeat,再调用 igh_cia402_send_targets_all() 或 igh_cia402_send_target_step() 发送目标位置。
如果需要预约发送,先启用 DC Sync0,再调用 igh_cia402_set_scheduled_tx();RPDO 目标和 SYNC 可以独立预约。
这样 demo 只作为 bring-up 和回归测试工具,客户自己的程序仍然可以沿用相同的启动、收发、诊断和预约能力。
15.6 运行 CiA402 demo
单电机 bring-up 示例默认使用从站 0、MCAN0、NodeID 1、1Mbps;首次 bring-up 建议显式使用 --step 0,避免主动运动:
sh Copy sudo ./build/igh_cia402_single_axis_demo \
--bitrate 1000000 \
--cycle-us 10000 \
--cycles 20 \
--step 0单板 CAN FD 或全量容量 bring-up 可显式使用 1024B PDO、较长周期和 1 个从站;classic CAN/CiA402 bring-up 通常保持 --pdo-n 3:
sh Copy sudo ./build/igh_cia402_10axis_demo \
--slaves 1 \
--pdo-n 8 \
--cycle-us 10000 \
--cycles 10000系统稳定后再缩短周期,例如 1ms:
sh Copy sudo ./build/igh_cia402_10axis_demo \
--slaves 1 \
--pdo-n 3 \
--cycle-us 1000 \
--cycles 10000 \
--dc-sync0 \
--dc-cycle-us 1000 \
--dc-shift-us 700常用参数:
启动阶段 demo 会写入 PDO profile、通道配置和 CAN FD TDC 默认值。TDCOffset=0、TDCFilter=0 表示固件按数据段时序自动计算;数据段达到 5M 及以上时固件强制启用 TDC。
15.6.1 IgH 三从站参考稳定点
以下为当前产品化 IgH adapter(per-slave domain)、三从站、CRC16 默认开启、base 模式、root + SCHED_FIFO + 绑核条件下的参考长测点。短测结果只用于筛选相位,产品配置应以 2 分钟或更长长测为准。
以上结果是参考边界,不等同于所有主机、网卡和线缆组合的保证值。若扩展到更大 PDO 或更多真实 CAN 负载,应同时观察 WKC、OP 状态、TxPDO header、0x9011 周期诊断和 0x9020..0x9023 每通道数据面诊断。
15.7 SII/EEPROM 与 SM 布局检查
设备 EEPROM/SII 必须保持大 PDO 单缓冲布局,否则 IgH OP/DC 运行会被错误 SM 配置干扰:
可用脚本手动检查:
sh Copy sudo scripts/ecan_sii_sm_layout.sh check \
--ethercat ../ethercat-install/bin/ethercat \
--position 0 \
--pdo-bytes 3072需要修复时必须人工确认后再执行:
sh Copy sudo scripts/ecan_sii_sm_layout.sh fix \
--ethercat ../ethercat-install/bin/ethercat \
--position 0 \
--pdo-bytes 3072
16. 调试与诊断
16.1 OP 异常
优先检查:
EEPROM/SII 中 SM2/SM3 是否为 0x1100/0x1D00、3072B、0x66/0x22。
0x1C12/0x1C13 assignment 数量是否与 0x8010/0x8011 PDO size multiplier 一致。
IgH adapter 是否使用 per-slave domain/FMMU 分段策略;旧示例或旧 master 再考虑大 PDO/FMMU 补丁。
DC shift 是否过小;输出数据未赶在 Sync0 前到达会造成 WC miss 或掉 OP。
16.2 PDO 解析错误
查看:
0x8010/0x8011 Status
LastPDOError
PDOErrorCounter
PDOOverflowCounter
IgH 协议层 parse_diag,包含 offset、packet_end、ctrl、seq、payload_len、payload_crc16、layout_id、ch、dlc、tsf、kind。
16.3 CAN 总线异常
查看:
PDO header 中 channel_status
0x9000..0x9003 的 ECR/PSR/IR/RXF0S/RXF1S/TXFQS/TXEFS
外部 CAN 工具的错误计数和终端电阻状态
波特率、采样点、TDC、CAN FD BRS 是否与对端一致
17. 验证结果数据
验证环境:
18. 技术规格
19. 修订历史
Copyright (c) 2026 LanMotion .