
SVG架构图总结了EtherCAT实时控制程序的所有关键要素:
图表包含以下主要部分:
- 主线程流程
- 显示程序初始化、配置和清理的完整生命周期
- 实时任务循环
- 详细展示1ms周期的实时控制循环,包括:
EtherCAT帧的接收和发送
域数据处理
状态监控
数字输出控制
- 信号处理机制
- 展示如何通过SIGTERM/SIGINT信号优雅地停止程序
- EtherCAT网络拓扑
- 可视化硬件配置:
主站 (Master)
总线耦合器 (EK1100)
数字输出模块 (EL2004) 及其4个输出通道
- 技术特性说明
- 总结关键的技术参数:
实时性能 (Xenomai, 1ms周期)
通信协议 (EtherCAT)
控制逻辑 (LED闪烁, 状态监控)
硬件配置 (Beckhoff模块)
- 数据流可视化
- 用不同颜色的箭头表示数据发送、接收和控制流
这个图表清晰地展示了工业自动化中EtherCAT实时通信系统的完整架构和工作原理。

这是一个基于 IgH EtherCAT Master 和 Xenomai 实时扩展的 C 语言示例程序。其核心功能是建立一个简单的 EtherCAT 网络,并以硬实时的方式周期性地控制一个数字量输出模块。
程序的主要流程如下:
初始化与配置:
在
main函数中,程序首先设置了信号处理(用于安全退出)和内存锁定(mlockall,防止内存交换以保证实时性)。请求并获取一个 EtherCAT 主站实例。
创建一个过程数据域 (Domain),用于管理周期性交换的数据。
为总线上的两个从站(一个
EK1100总线耦合器和一个EL2004四通道数字量输出模块)创建配置。为
EL2004配置其 PDO (过程数据对象),并将其中一个输出通道的 PDO 条目注册到之前创建的域中,这样就可以通过读写域的内存来控制该输出。
激活与实时任务:
激活 EtherCAT 主站,使其开始在总线上与从站进行周期性通信。
获取指向域过程数据内存区域的指针
domain1_pd。创建一个高优先级的 Xenomai 实时任务 (
my_task),并启动它。这个任务将以 1毫秒 的固定周期运行。
实时循环 (
my_task_proc):ecrt_master_receive(): 接收从站发回的数据帧。
ecrt_domain_process(): 将接收到的数据更新到域内存中。
- 应用逻辑
: 程序的核心逻辑在这里。它维护一个
blink变量,每 200ms 翻转一次状态(0/1切换)。然后,根据blink的状态,通过EC_WRITE_U8宏向过程数据内存区写入0x0F(全开) 或0x00(全关),从而控制EL2004的输出通道。 ecrt_domain_queue(): 将要发送的数据(即刚刚写入的控制命令)准备好。
ecrt_master_send(): 将数据帧发送给从站。
在每个 1ms 的周期内,任务执行标准的 EtherCAT 通信流程:
任务还周期性地检查并打印主站和域的状态,用于监控和调试。
程序终止:
main函数在启动实时任务后,会进入一个低优先级的
while循环,通过sched_yield()让出CPU。当用户按下
Ctrl+C或发送SIGTERM信号时,signal_handler会被调用,将全局标志run置为0。实时任务的
while循环和主函数的while循环都会因此而退出。程序随后执行清理工作:删除实时任务,释放 EtherCAT 主站资源,然后正常退出。
总而言之,这是一个教科书式的 EtherCAT 硬实时控制示例,展示了从硬件配置、实时任务创建到周期性数据交换和应用逻辑实现的完整过程。


这个图表展示了程序的三个主要执行线程:
- 主线程
:负责初始化EtherCAT系统、创建和管理实时任务
- 实时任务线程
:执行1ms周期的实时控制循环,处理EtherCAT通信
- 信号处理
:异步处理系统信号以优雅地停止程序
图中的关键要素包括:
- 初始化阶段
:内存锁定、主站请求、域创建、从站配置
- 实时循环
:1ms周期的EtherCAT通信(接收→处理→发送)
- 状态监控
:定期检查主站和域的工作状态
- 数字输出控制
:200ms周期的LED闪烁控制
- 优雅退出
:通过信号处理机制安全停止程序
这个泳道图清晰地展示了Xenomai实时系统中多线程并行执行的特点,以及EtherCAT实时通信的周期性特征。
#include <errno.h> // 包含C标准库头文件,用于错误码处理(例如 strerror 函数)#include <signal.h> // 包含信号处理头文件,用于捕获如 SIGINT, SIGTERM 等中断信号#include <stdio.h> // 包含标准输入输出头文件,用于 printf, fprintf 等函数#include <string.h> // 包含字符串处理头文件,用于 strerror 等函数#include <sys/resource.h> // 包含系统资源操作头文件,虽然在此代码中未直接使用其函数,但常用于实时系统设置优先级#include <sys/time.h> // 包含时间相关头文件,定义了时间结构体#include <sys/types.h> // 包含基本系统数据类型头文件#include <unistd.h> // 包含 POSIX 标准 API 头文件,提供对操作系统服务的访问(如 sched_yield)#include <sys/mman.h> // 包含内存管理声明头文件,用于 mlockall 函数,防止内存交换#ifdef XENOMAI_API_V3 // C预处理器指令,检查是否定义了 XENOMAI_API_V3 宏#include <alchemy/task.h> // 如果是 Xenomai 3.x,包含 Alchemy API 的任务管理头文件#include <alchemy/sem.h> // 如果是 Xenomai 3.x,包含 Alchemy API 的信号量头文件enum {T_FPU = 0}; // 为 Xenomai 3.x 定义 T_FPU 枚举(表示不使用FPU),以兼容 2.x 的 API#else // 如果没有定义 XENOMAI_API_V3#include <rtdm/rtdm.h> // 包含实时驱动模型(RTDM)头文件#include <native/task.h> // 包含 Xenomai 2.x Native API 的任务管理头文件#include <native/sem.h> // 包含 Xenomai 2.x Native API 的信号量头文件#include <native/mutex.h> // 包含 Xenomai 2.x Native API 的互斥锁头文件#include <native/timer.h> // 包含 Xenomai 2.x Native API 的定时器头文件#include <rtdk.h> // 包含 Xenomai 的实时打印(rt_printf)头文件#endif // 结束 #ifdef 条件编译块#include <pthread.h> // 包含 POSIX 线程库头文件,虽然主实时逻辑用Xenomai,但可能用于非实时部分#include "ecrt.h" // 包含 IgH EtherCAT 主站的核心应用层 API 头文件RT_TASK my_task; // 声明一个 Xenomai 实时任务(RT_TASK)变量,名为 my_taskstatic volatile sig_atomic_t run = 1; // 声明一个静态的、易失的、信号安全的整型变量 run,并初始化为1。用作主循环的运行标志。/****************************************************************************/ // 分隔注释// EtherCAT // 区域注释:EtherCAT 相关变量static ec_master_t *master = NULL; // 声明一个静态的 EtherCAT 主站对象指针,并初始化为 NULLstatic ec_master_state_t master_state = {}; // 声明一个静态的主站状态结构体变量,并使用聚合初始化将其清零static ec_domain_t *domain1 = NULL; // 声明一个静态的 EtherCAT 过程数据域(Domain)指针,并初始化为 NULLstatic ec_domain_state_t domain1_state = {}; // 声明一个静态的域状态结构体变量,并清零static uint8_t *domain1_pd = NULL; // 声明一个静态的指向过程数据(Process Data)内存区域的8位无符号整型指针,并初始化为 NULLstatic ec_slave_config_t *sc_dig_out_01 = NULL; // 声明一个静态的从站配置对象指针,用于配置数字量输出从站,并初始化为 NULL/****************************************************************************/ // 分隔注释// process data // 区域注释:过程数据相关定义#define BusCoupler01_Pos 0, 0 // 宏定义:总线耦合器(Bus Coupler)的位置,别名 (主站索引0, 站地址0)#define DigOutSlave01_Pos 0, 1 // 宏定义:数字量输出从站(Digital Out Slave)的位置,别名 (主站索引0, 站地址1)#define Beckhoff_EK1100 0x00000002, 0x044c2c52 // 宏定义:倍福 EK1100 的厂商ID和产品代码#define Beckhoff_EL2004 0x00000002, 0x07d43052 // 宏定义:倍福 EL2004 的厂商ID和产品代码// offsets for PDO entries // 注释:PDO条目的偏移量static unsigned int off_dig_out0 = 0; // 声明一个静态无符号整型变量,用于存储某个PDO条目在过程数据域中的字节偏移量// process data // 区域注释:过程数据const static ec_pdo_entry_reg_t domain1_regs[] = { // 定义一个静态常量数组,用于注册需要映射到域的PDO条目 {DigOutSlave01_Pos, Beckhoff_EL2004, 0x7000, 0x01, &off_dig_out0, NULL}, // 第一个条目:从站位置、厂商/产品ID、PDO索引、PDO子索引、偏移量存储地址、无bit偏移 {} // 数组结束标志,一个内容全为0的空结构体};/****************************************************************************/ // 分隔注释/* Slave 1, "EL2004" // 注释:从站1 "EL2004" 的详细信息 * Vendor ID: 0x00000002 // 厂商ID * Product code: 0x07d43052 // 产品代码 * Revision number: 0x00100000 // 修订号 */const ec_pdo_entry_info_t slave_1_pdo_entries[] = { // 定义一个静态常量数组,描述 EL2004 从站的所有可用 PDO 条目 {0x7000, 0x01, 1}, /* Output */ // 条目1:索引0x7000,子索引0x01,位长度1 (第一个输出通道) {0x7010, 0x01, 1}, /* Output */ // 条目2:索引0x7010,子索引0x01,位长度1 (第二个输出通道) {0x7020, 0x01, 1}, /* Output */ // 条目3:索引0x7020,子索引0x01,位长度1 (第三个输出通道) {0x7030, 0x01, 1}, /* Output */ // 条目4:索引0x7030,子索引0x01,位长度1 (第四个输出通道)};const ec_pdo_info_t slave_1_pdos[] = { // 定义一个静态常量数组,描述 EL2004 从站的 PDO 配置 {0x1600, 1, slave_1_pdo_entries + 0}, /* Channel 1 */ // PDO 1: RxPDO 0x1600, 包含1个条目, 条目信息从 slave_1_pdo_entries[0] 开始 {0x1601, 1, slave_1_pdo_entries + 1}, /* Channel 2 */ // PDO 2: RxPDO 0x1601, 包含1个条目, 条目信息从 slave_1_pdo_entries[1] 开始 {0x1602, 1, slave_1_pdo_entries + 2}, /* Channel 3 */ // PDO 3: RxPDO 0x1602, 包含1个条目, 条目信息从 slave_1_pdo_entries[2] 开始 {0x1603, 1, slave_1_pdo_entries + 3}, /* Channel 4 */ // PDO 4: RxPDO 0x1603, 包含1个条目, 条目信息从 slave_1_pdo_entries[3] 开始};ec_sync_info_t slave_1_syncs[] = { // 定义一个数组,描述 EL2004 从站的同步管理器(Sync Manager)配置 {0, EC_DIR_OUTPUT, 4, slave_1_pdos + 0, EC_WD_ENABLE}, // Sync Manager 0: 类型为输出(OUTPUT), 关联4个PDO, PDO信息从 slave_1_pdos[0] 开始, 启用看门狗(Watchdog) {0xff} // 数组结束标志,同步管理器索引为0xff};/***************************************************************************** * Realtime task // 区域注释:实时任务相关函数 ****************************************************************************/void rt_check_domain_state(void) // 定义一个函数,用于检查并打印域的状态变化{ ec_domain_state_t ds = {}; // 声明一个局部的域状态结构体变量 ds,并清零ecrt_domain_state(domain1, &ds); // 调用 ecrt API,获取 domain1 的当前状态,并存入 ds if (ds.working_counter != domain1_state.working_counter) { // 比较当前工作计数器(WC)与上次记录的WC rt_printf("Domain1: WC %u.\n", ds.working_counter); // 如果不一致,使用实时打印函数输出新的WC值 } if (ds.wc_state != domain1_state.wc_state) { // 比较当前工作计数器状态与上次记录的状态 rt_printf("Domain1: State %u.\n", ds.wc_state); // 如果不一致,输出新的WC状态值 } domain1_state = ds; // 将当前状态 ds 赋值给全局的 domain1_state,用于下次比较}/****************************************************************************/ // 分隔注释void rt_check_master_state(void) // 定义一个函数,用于检查并打印主站的状态变化{ ec_master_state_t ms; // 声明一个局部的主站状态结构体变量 msecrt_master_state(master, &ms); // 调用 ecrt API,获取主站的当前状态,并存入 ms if (ms.slaves_responding != master_state.slaves_responding) { // 比较当前响应的从站数量与上次记录的数量 rt_printf("%u slave(s).\n", ms.slaves_responding); // 如果不一致,输出新的从站数量 } if (ms.al_states != master_state.al_states) { // 比较当前应用层(AL)状态与上次记录的状态 rt_printf("AL states: 0x%02X.\n", ms.al_states); // 如果不一致,以十六进制格式输出新的AL状态 } if (ms.link_up != master_state.link_up) { // 比较当前链路连接状态与上次记录的状态 rt_printf("Link is %s.\n", ms.link_up ? "up" : "down"); // 如果不一致,输出链路是 "up" 还是 "down" } master_state = ms; // 将当前状态 ms 赋值给全局的 master_state,用于下次比较}/****************************************************************************/ // 分隔注释void my_task_proc(void *arg) // 定义实时任务的主体函数,参数为 void 指针{int cycle_counter = 0; // 定义一个整型变量,用作周期计数器,并初始化为0 unsigned int blink = 0; // 定义一个无符号整型变量,用作闪烁标志,并初始化为0rt_task_set_periodic(NULL, TM_NOW, 1000000); // 设置当前任务(NULL表示自身)为周期性任务,立即(TM_NOW)开始,周期为 1,000,000 纳秒 (1毫秒)while (run) { // 循环,只要全局变量 run 为1就一直执行rt_task_wait_period(NULL); // 等待下一个周期性调度点的到来(阻塞当前任务) cycle_counter++; // 周期计数器加1// receive EtherCAT frames // 注释:接收 EtherCAT 帧ecrt_master_receive(master); // 从网络接口接收数据帧,放入主站的内部缓冲区ecrt_domain_process(domain1); // 处理域的数据,将接收到的数据解包到过程数据(PD)内存区rt_check_domain_state(); // 调用函数检查并打印域的状态变化if (!(cycle_counter % 1000)) { // 判断周期计数器是否是1000的倍数(即每1000个周期/1秒执行一次)rt_check_master_state(); // 调用函数检查并打印主站的状态变化 }if (!(cycle_counter % 200)) { // 判断周期计数器是否是200的倍数(即每200个周期/200毫秒执行一次) blink = !blink; // 对 blink 变量取反(0变1,1变0),实现闪烁逻辑 }EC_WRITE_U8(domain1_pd + off_dig_out0, blink ? 0x0 : 0x0F); // 将数据写入过程数据区。如果blink为true(1),写入0x00;如果为false(0),写入0x0F。这里控制4个通道同时开关// send process data // 注释:发送过程数据ecrt_domain_queue(domain1); // 将域中需要发送的数据(刚写入的)放入主站的发送队列ecrt_master_send(master); // 将发送队列中的数据帧通过网络接口发送出去 }}/**************************************************************************** * Signal handler // 区域注释:信号处理器 ***************************************************************************/void signal_handler(int sig) // 定义信号处理函数,参数为信号编号{ run = 0; // 将全局运行标志 run 设置为0,使主循环和实时任务循环 gracefully 退出}/**************************************************************************** * Main function // 区域注释:主函数 ***************************************************************************/int main(int argc, char *argv[]) // C程序的入口主函数{ ec_slave_config_t *sc; // 声明一个局部的从站配置对象指针 int ret; // 声明一个整型变量,用于存储函数返回值#ifndef XENOMAI_API_V3 // C预处理器指令,检查是否没有定义 XENOMAI_API_V3 (即 Xenomai 2.x) /* Perform auto-init of rt_print buffers if the task doesn't do so */ // 注释:如果任务不自己初始化,则自动初始化rt_print缓冲区 rt_print_auto_init(1); // 自动初始化 Xenomai 的实时打印缓冲区#endif // 结束 #ifndef 条件编译块 signal(SIGTERM, signal_handler); // 注册信号处理器,当收到终止信号(SIGTERM)时调用 signal_handler 函数 signal(SIGINT, signal_handler); // 注册信号处理器,当收到中断信号(SIGINT, e.g., Ctrl+C)时调用 signal_handler 函数 mlockall(MCL_CURRENT | MCL_FUTURE); // 锁定当前和未来所有分配的内存,防止被交换到磁盘,确保实时性 printf("Requesting master...\n"); // 在控制台打印提示信息 master = ecrt_request_master(0); // 请求索引为0的 EtherCAT 主站实例 if (!master) { // 检查主站请求是否成功 return -1; // 如果失败(返回NULL),程序返回-1并退出 } domain1 = ecrt_master_create_domain(master); // 在主站上创建一个过程数据域 if (!domain1) { // 检查域创建是否成功 return -1; // 如果失败,程序返回-1并退出 } printf("Creating slave configurations...\n"); // 在控制台打印提示信息 // Create configuration for bus coupler // 注释:为总线耦合器创建配置 sc = ecrt_master_slave_config(master, BusCoupler01_Pos, Beckhoff_EK1100); // 为位置(0,0)的EK1100总线耦合器创建从站配置 if (!sc) { // 检查配置创建是否成功 return -1; // 如果失败,程序返回-1并退出 } sc_dig_out_01 = // 为数字量输出从站创建配置,并将其地址存入全局指针 ecrt_master_slave_config(master, DigOutSlave01_Pos, Beckhoff_EL2004); // 为位置(0,1)的EL2004从站创建配置 if (!sc_dig_out_01) { // 检查配置创建是否成功 fprintf(stderr, "Failed to get slave configuration.\n"); // 向标准错误输出流打印错误信息 return -1; // 如果失败,程序返回-1并退出 } if (ecrt_slave_config_pdos(sc_dig_out_01, EC_END, slave_1_syncs)) { // 为 EL2004 从站配置 PDO 和同步管理器 fprintf(stderr, "Failed to configure PDOs.\n"); // 如果配置失败,打印错误信息 return -1; // 并返回-1退出 } if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) { // 将定义的 PDO 注册列表注册到域中 fprintf(stderr, "PDO entry registration failed!\n"); // 如果注册失败,打印错误信息 return -1; // 并返回-1退出 } printf("Activating master...\n"); // 在控制台打印提示信息 if (ecrt_master_activate(master)) { // 激活主站,开始进行总线通信 return -1; // 如果激活失败,返回-1退出 } if (!(domain1_pd = ecrt_domain_data(domain1))) { // 获取域的过程数据内存区的指针 fprintf(stderr, "Failed to get domain data pointer.\n"); // 如果获取失败(返回NULL),打印错误信息 return -1; // 并返回-1退出 } ret = rt_task_create(&my_task, "my_task", 0, 80, T_FPU); // 创建一个 Xenomai 实时任务 // 参数:任务句柄地址, 任务名, 栈大小(0=默认), 优先级(80), 浮点运算单元(FPU)选项 if (ret < 0) { // 检查任务创建是否成功 fprintf(stderr, "Failed to create task: %s\n", strerror(-ret)); // 如果失败,打印错误信息(使用strerror将错误码转为字符串) return -1; // 并返回-1退出 } printf("Starting my_task...\n"); // 在控制台打印提示信息 ret = rt_task_start(&my_task, &my_task_proc, NULL); // 启动已创建的实时任务 // 参数:任务句柄, 任务函数指针, 传递给任务的参数 if (ret < 0) { // 检查任务启动是否成功 fprintf(stderr, "Failed to start task: %s\n", strerror(-ret)); // 如果失败,打印错误信息 return -1; // 并返回-1退出 }while (run) { // 主线程进入一个等待循环,只要 run 标志为1sched_yield(); // 主动让出 CPU,让其他任务(特别是实时任务)运行 } printf("Deleting realtime task...\n"); // 在收到退出信号后,打印提示信息 rt_task_delete(&my_task); // 删除 Xenomai 实时任务 printf("End of Program\n"); // 打印程序结束信息 ecrt_release_master(master); // 释放之前请求的 EtherCAT 主站资源 return 0; // 程序正常退出,返回0}
IgH EtherCAT 是一个专为 Linux 平台设计的 开源 EtherCAT 主站协议栈,由德国 EtherLab 项目开发,广泛应用于工业自动化、机器人控制和实时运动控制系统中。下面是它的简要介绍:
🧠 项目概述
- 全称
:IgH EtherCAT Master
- 开发平台
:Linux(支持 RTAI、Xenomai、RT-Preempt 等实时扩展)
- 协议支持
:完整支持 EtherCAT 协议,包括 COE、SOE、EOE、分布式时钟(DC)等
- 开源协议
:GPL 许可,免费使用和修改
- 官网
:etherlab.org
🔧 核心功能
构建 Linux 字符设备,应用程序通过访问该设备与主站模块通信
提供命令行工具,可直接操作从站设备(如设置地址、读写 PDO/SDO)
支持多种网卡驱动方式:
- Generic 驱动
:适用于所有网卡,依赖 Linux 网络协议栈
- Native 驱动
:针对特定网卡,可直接操作硬件,实时性更强
- Generic 驱动
🧩 使用场景
实时控制系统(如机器人、数控机床、自动化产线)
教育与研究(开源特性便于教学和实验)
商业应用(已有多个专利和产品基于该项目)
🔍 与 SOEM 的对比
特性
IgH EtherCAT Master
SOEM (Simple Open EtherCAT Master)
功能完整性
✅ 高
⚠️ 较简化
平台依赖
Linux + 实时内核
可移植至嵌入式平台(如 MCU)
实时性支持
强(支持 DC、RT 扩展)
中等
使用复杂度
较高
较低
适用场景
工业级控制系统
资源受限的嵌入式应用
如果你正在做机器人控制或工业自动化项目,IgH EtherCAT 是一个功能强大且成熟的主站实现。需要我帮你梳理它的架构或如何将它集成到你的系统中吗?我可以按模块逐步解析。
🏗️ IgH EtherCAT 主站结构图
📌 图示说明
每个组件对应一个功能模块或设备节点
箭头代表控制流或数据流方向
Driver可以是通用或原生网卡驱动,取决于配置
FSM和
Mailbox是主站内部的子模块,但在源码中也有较独立的逻辑实现
🔄 状态机模块结构图(State Machines)
📌 说明:
每个状态机模块负责 EtherCAT 总线的某一阶段。
状态机之间是顺序执行关系,支持嵌套与子状态机调用。
可扩展为状态图或流程图,适合教学用途。
📡 Mailbox 协议模块结构图(Mailbox Protocols)
📌 说明:
所有协议处理器由主模块调用,处理 Mailbox 通信。
可根据从站类型启用不同协议(如伺服驱动器使用 SoE)。
下面我将为你逐一介绍 IgH EtherCAT Master 的主要模块及其具体功能,保持模块级粒度,便于你后续做文档映射或教学拆解:
🧠 1.
ec_master.ko(主站内核模块)创建 EtherCAT 主站实例,每个实例对应
/dev/EtherCATX字符设备管理从站扫描、状态切换、PDO 映射、DC 同步等核心流程
支持多个主站并行运行(通过
master_count参数)提供统一的设备接口供网卡驱动绑定
实现 Mailbox 协议解析(CoE、SoE、EoE、VoE)
🔌 2. 网卡驱动模块(如
ec_igb.ko,ec_generic.ko)- Native 驱动
:直接操作网卡硬件,禁用中断,实现高实时性
- Generic 驱动
:使用 Linux 网络协议栈,兼容性强但实时性较弱
通过 MAC 地址与主站实例绑定,实现数据收发
可支持冗余网卡配置(主/备网卡)
📁 3. 字符设备接口(
/dev/EtherCATX)用户空间程序通过
ioctl与主站通信支持并发访问、线程安全
提供从站配置、PDO 映射、状态查询等接口
是用户态与内核态的桥梁
🧰 4. 用户空间工具与库
a.
ethercatctl(命令行工具)扫描从站设备
显示设备信息(如
ethercat slaves -v)设置 PDO 映射、状态切换、DC 同步等
b.
libethercat(用户态 C 接口库)提供应用程序访问 EtherCAT 主站的 API
支持周期性数据交换、状态监控
可嵌入实时任务中运行(如周期性
cyclic_task())
⚙️ 5. 启动与配置脚本
ethercat.conf:配置网卡、驱动类型、调试级别等
init.d/
systemd脚本:加载主站模块、驱动、创建设备节点支持自动创建 EoE handler、设置 pcap 缓冲区等高级参数
🔄 6. 状态机模块(State Machines)
模块名称
功能描述
主站状态机
管理主站生命周期(Orphaned → Idle → Operational)
从站扫描状态机
自动发现连接的从站设备
从站配置状态机
配置 PDO 映射、同步管理
状态变更状态机
控制从站状态切换(Init → PreOp → SafeOp → Op)
SII 状态机
读取从站 EEPROM 中的配置信息
PDO 状态机
管理过程数据交换的映射与更新
📡 7. Mailbox 协议支持模块
协议类型
功能描述
CoE(CANopen)
访问对象字典,配置参数
SoE(Servo)
控制伺服驱动器
EoE(Ethernet)
实现 IP 通信透传
VoE(Vendor)
支持厂商自定义协议
参考网址
https://wenku.youkuaiyun.com/column/ganm3d55zd
2955

被折叠的 条评论
为什么被折叠?



