跳到主要内容

C SDK 概述

纯 C 原生接口,用于开发 EtherCAT 主站应用,适合嵌入式与资源受限设备。

安装

两种使用方式:

方式一:动态加载(推荐) — 定义 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,链接导入库 Darra.Core.lib

# MSVC 静态链接
cl /Fe:my_app.exe main.c Darra.Core.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(实时网络访问)
  • 实时内核驱动 — 随安装包提供,微秒级实时、无需专用硬件,见 Windows 驱动

快速开始

使用 Darra 配置工具
  1. 打开 Darra 配置工具,扫描 EtherCAT 网络
  2. 配置从站参数(PDO 映射、DC 设置等)
  3. 导出 DENI 配置文件
  4. 在代码中加载 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 用于生产环境(一行加载全套参数),自动搜索用于演示 / 工具类应用。

核心概念:

  • 主站索引uint16_t 标识主站实例,Initialize() 返回(>0 成功)
  • dll_t 结构体 — 动态加载模式下持有所有导出函数指针,经 dll.FuncName() 调用
  • 多实例 — 每个主站实例管一条独立总线,用不同网卡,CPU 核心可独立分配

高级 API

ethercat_advanced.h 提供一组高级封装,简化常见流程:

功能API 函数 / 头文件说明
一步初始化EcInit / EcInitFromFile / EcCloseJSON 配置一步完成主站初始化
状态链转换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 Pingeoe_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+)

<sugar/sugar.h> 提供一组可选的 macros + inline 包装,零运行时成本,不影响标准 API。详见 C 特有语法糖,包含:结构指定初始化 ({ .cycle_ns = 1000000 }) / 遍历宏 EC_FOREACH_SLAVE(mi, i) / 错误处理 EC_TRY · EC_TRY_LOG · EC_RETURN_IF_FAIL · EC_GOTO_IF_FAIL / inline 短名 getter ec_vendor · ec_product / GCC/Clang cleanup EC_AUTO_DISPOSE / 周期预设 EC_PRESET_CYCLE_1MS / C11 _Generic 类型分发。

自动健康检查

启动时自动校验驱动版本与 RT 核隔离,不匹配在 SDK 日志中写 Warning。

错误码本地化

AL Status 描述支持中英双语,默认英文:

darra_driver_version_t drv;
darra_get_driver_version(&drv); // 内核驱动版本
const char* en = AL_StatusCode_GetDescription(code); // English (默认)

版本兼容

当前 SDK 版本 2.7.x。PATCH 兼容,MINOR / MAJOR 必须重装配套驱动 —— 详见 SDK 版本兼容

运行时通过 GetDllVersionInfo() 查询实际 DLL 版本,详见 DLL 版本信息