C SDK 概述
DarraEtherCAT C SDK 提供了用于开发 EtherCAT 主站应用程序的纯 C 原生接口,直接封装底层运行时库,支持主站与从站之间的高速实时通信。
安装
C SDK 提供两种使用方式:
方式一:动态加载(推荐) — 定义 DYNAMIC_LOAD 宏,运行时通过 LOAD_DLL() 加载 DLL,所有函数通过 dll_t 结构体中的函数指针调用。无需链接 .lib 文件。
#define DYNAMIC_LOAD
#include "ethercat.h"
int main(void) {
dll_t dll;
if (!LOAD_DLL(&dll, "DarraEtherCAT.dll")) return 1;
uint16_t master = dll.Initialize();
/* ... 通过 dll.FuncName() 调用所有函数 ... */
dll.Dispose(master);
UNLOAD_DLL(&dll);
return 0;
}
方式二:静态链接 — 不定义 DYNAMIC_LOAD,直接声明函数原型,链接 SDK 附带的导入库 DarraEtherCAT.lib。
# MSVC 静态链接
cl /Fe:my_app.exe main.c DarraEtherCAT.lib /I include
# MSVC 动态加载 (无需 .lib)
cl /Fe:my_app.exe main.c /I include /DDARRA_DYNAMIC_LOAD
# GCC/MinGW 动态加载
gcc main.c -I include -DDARRA_DYNAMIC_LOAD -o my_app.exe
系统要求
| 项目 | 要求 |
|---|---|
| 操作系统 | Windows 7+(推荐 Windows 10/11)/ Linux |
| 编译器 | MSVC 2019+、GCC 7+、Clang 10+ |
| 标准 | C11 或更高 |
| 网络适配器 | 常规以太网网卡 |
| 权限 | 管理员/root 权限 |
安装 DarraRT 驱动
DarraRT 驱动 提供微秒级实时性能,完全免费。详见 下载页面。
优势:< 1us 抖动 · 最优 DC 同步 · 纯软件实时 · 无需专用硬件
快速开始
- 打开 Darra 配置工具,扫描 EtherCAT 网络
- 配置从站参数(PDO 映射、DC 设置等)
- 导出 DENI 配置文件
- 在代码中加载 DENI 文件初始化主站
#include <stdio.h>
#include <ethercat.h>
int main(void) {
/* ★ 推荐方式: 使用 DENI 文件一步初始化
(内部 = Initialize + SetNetwork + LoadConfig + SetStateSequence + Start) */
uint16_t m = EcInitFromFile("C:\\EtherCAT\\MyProject.deni");
if (m == 0) { fprintf(stderr, "DENI 加载失败\n"); return 1; }
/* 已自动进 OP, 这里直接通信 */
int n = 0;
char* sw = dx_sdo_read(m, 1, 0x6041, 0x00, FALSE, &n);
if (sw && n >= 2) {
printf("Statusword=0x%04X\n", *(uint16_t*)sw);
}
if (sw) FreeMemory(sw);
EcClose(m); /* 一步关闭: Stop + Dispose */
return 0;
}
备选方式: 自动搜索网卡 (无 DENI 时)
不使用 DENI 时, 用 GetNetworkInfo() 自动扫描所有网卡, 取有从站的那张, 不必硬编码 \Device\NPF_{GUID}:
#include <stdio.h>
#include <ethercat.h>
int main(void) {
/* 扫所有 NIC 并探测从站数 (耗时 ~500ms-1.5s) */
int n = GetNetworkInfo(FALSE, TRUE);
ec_networkInfo* nets = (ec_networkInfo*)GetNetworksPointer(); /* 内部指针, 无需释放 */
/* 选有从站的 NIC */
uint16_t m = Initialize();
int found = 0;
for (int i = 0; i < n; i++) {
if (nets[i].slaveNum > 0) {
printf("找到: %s (从站 %d 台)\n", nets[i].desc, nets[i].slaveNum);
SetNetwork(m, nets[i].name, "");
found = 1;
break;
}
}
if (!found) { fprintf(stderr, "未发现 EtherCAT 网络\n"); Dispose(m); return 1; }
SetStateSequence(m, EC_STATE_OPERATIONAL, 10000);
Start(m);
/* ... 通信 ... */
Stop(m);
Dispose(m);
return 0;
}
- DENI — 生产环境, 一行加载 ESI/PDO/DC 全套参数, 推荐.
- 自动搜索 — 演示 / 工具类应用 / 不需要预配置启动参数的场景.
核心概念:
- 主站索引 (master_index) —
uint16_t标识主站实例。Initialize()返回(>0 成功) - dll_t 结构体 — 动态加载模式下包含所有 DLL 导出函数指针,通过
dll.FuncName()调用 - 多实例 — 每个主站实例管理一条独立的 EtherCAT 总线,使用不同的网卡,CPU 核心可独立分配
高级 API
SDK 提供了一组高级 API,简化常见操作流程。ethercat_advanced.h 头文件提供更多便捷封装:
| 功能 | API 函数 / 头文件 | 说明 |
|---|---|---|
| 一步初始化 | EcInit / EcInitFromFile / EcClose | JSON 配置一步完成主站初始化 |
| 状态链转换 | SetStateSequence | 自动执行多步状态转换链 |
| 启动参数管线 | AddStartupParameter / ApplyStartupParameters | 批量添加启动参数并一次性应用 |
| CiA 402 驱动状态机 | CiA402_Enable / CiA402_SetMode | 一步使能 / 故障复位 / 状态解析 |
| EMCY 紧急消息缓冲 | EmcyGetCount / EmcyGetHistory | 读取从站紧急消息历史 |
| PDO 类型化读写 | PDOReadInputU16 / PDOWriteOutputI32 等 | 按类型直接读写 PDO 数据 |
| 拓扑查询 | TopologyBuild / TopologyGetRoots / TopologyGetChildren | 构建并查询从站网络拓扑树 |
| OD 树遍历 | od_load() | 加载完整对象字典树 |
| MDP 模块发现 | mdp_discover() / mdp_get_detected_module_list() | 模块化设备扫描 |
| MDP 自动编排 | MDPAutoEnumerate | 模块化设备进 OP 自动配置 |
| 异步邮箱事务 | ec_mbx_submit_async / ec_mbx_wait | 非阻塞邮箱事务管线 |
| 从站实时状态 | GetSlaveStateLive / GetSlaveALStatusCodeLive | 当周期从站状态 / AL 错误码直读 |
| FSoE 管理器 | fsoe_manager_create() | 多连接管理 |
| EoE Ping | eoe_ping() | ICMP Ping |
| PDO 变化监视器 | pdo_monitor_create() | 输入数据变化检测 |
快速示例:
/* 一步使能伺服驱动器 (slave=1, max_retries=50) */
dll.CiA402_Enable(master, 1, 50);
/* 类型化 PDO 读写 */
uint16_t status = PDOReadInputU16(master, 1, 0);
PDOWriteOutputI32(master, 1, 2, 100000);
/* 读取紧急消息历史 (调用者提供 ec_emcy_record_t 缓冲, 返回写入条数) */
ec_emcy_record_t records[16];
int n = dll.EmcyGetHistory(master, 1, records, 16);
/* 拓扑查询 */
uint16_t children[64];
int cn = dll.TopologyGetChildren(master, 1, children, 64);
C 特有语法糖 (C99+)
除标准 API 外, C SDK 在 <sugar/sugar.h> 头文件提供一组 macros + inline 包装, 全部零运行时成本. 详见 C 特有语法糖 — 包含结构指定初始化 ({ .cycle_ns = 1000000 }) / EC_FOREACH_SLAVE(mi, i) 遍历宏 / EC_TRY(call) / EC_TRY_LOG / EC_RETURN_IF_FAIL / EC_GOTO_IF_FAIL 错误处理 / ec_vendor / ec_product 等 inline 短名 getter / GCC/Clang EC_AUTO_DISPOSE cleanup attribute / 周期预设 (EC_PRESET_CYCLE_1MS) / _Generic (C11) 类型分发. 这些是可选的, 不影响标准 API 使用.
自动健康检查 · Auto health checks
master.Build() 时自动跑, 不匹配 → SDK 日志 Warning:
- 驱动版本比对 — 运行时库查询内核驱动版本, 跟 SDK MAJOR.MINOR 比, 不一致提示更新驱动
- RT 核隔离 — 后台检测 RT 核隔离配置是否就绪, 缺失提示重装 SDK
错误码本地化 · Error localization
AL Status 描述双语. SDK 默认英文, 中文专用接口给 UI:
darra_driver_version_t drv;
darra_get_driver_version(&drv); // 内核驱动版本
const char* en = AL_StatusCode_GetDescription(code); // English (默认)
版本兼容
当前 SDK 版本 2.7.x。
- 同 MAJOR.MINOR 内 PATCH 互相兼容 (例 2.7.0 ↔ 2.7.9), 包管理器升级即可, 不需重装驱动
- MAJOR / MINOR 变化 → 必须重装配套的驱动安装包, 否则会报版本兼容错误
- 运行时通过
GetDllVersionInfo()查询实际 DLL 版本, 详见 DLL 版本信息