跳到主要内容

从站 API

所有从站函数使用 uint16_t master_index 和 uint16_t slave_index(1-based)参数。

快速开始​

#include "ethercat.h"

uint16_t master = Initialize();
uint16_t count = SetNetwork(master, "\\Device\\NPF_{GUID}", "");
printf("从站总数: %u\n", count);

/* 读取从站信息 (slave_index 1-based) */
char name[128];
GetSlaveName(master, 1, name, sizeof(name));
uint32_t vid = GetSlaveVendorId(master, 1);
uint32_t pid = GetSlaveProductCode(master, 1);
printf("从站1: %s VID=0x%08X PID=0x%08X\n", name, vid, pid);

索引与组访问​

/* 通过 master_index + slave_index 直接访问, slave_index 1-based */
char name[128];
GetSlaveName(master, 1, name, sizeof(name));

/* 组1(默认组)从站数 */
uint16_t group_count = GetGroupSlaveCount(master, 1);
提示

组相关函数详见 从站分组。

地址与标识​

/* 物理配置地址(自动分配) */
uint16_t addr = GetSlaveConfigAddr(master, 1); /* 如 0x1001 */
uint16_t alias = GetSlaveAliasAddr(master, 1); /* EEPROM 别名 */

/* 标识 */
char name[128];
GetSlaveName(master, 1, name, sizeof(name));
uint32_t vid = GetSlaveVendorId(master, 1);
uint32_t pid = GetSlaveProductCode(master, 1);
uint32_t rev = GetSlaveRevision(master, 1);
uint32_t sn = GetSlaveSerialNumber(master, 1);

IO 区与邮箱属性​

/* PDO 区位数 / 字节数 / IOmap 偏移 / 起始位 */
uint16_t in_bits = GetSlaveInputBits(master, 1);
uint32_t in_bytes = GetSlaveInputBytes(master, 1);
uint32_t in_off = GetSlaveInputOffset(master, 1);
uint8_t in_sbit = GetSlaveInputStartBit(master, 1);

uint16_t out_bits = GetSlaveOutputBits(master, 1);
uint32_t out_bytes = GetSlaveOutputBytes(master, 1);
uint32_t out_off = GetSlaveOutputOffset(master, 1);
uint8_t out_sbit = GetSlaveOutputStartBit(master, 1);

/* DC 状态与时间 */
BOOL has_dc = GetSlaveHasDC(master, 1);
int32_t cycle0 = GetSlaveDCCycle0(master, 1);
int32_t shift = GetSlaveDCShift(master, 1);
int32_t pd = GetSlavePropagationDelay(master, 1);

/* 邮箱协议与缓冲区 */
uint16_t mbx_proto = GetSlaveMailboxProto(master, 1);
uint16_t mbx_wr_len = GetSlaveMailboxWriteLength(master, 1);
uint16_t mbx_rd_len = GetSlaveMailboxReadLength(master, 1);

详见 从站 IO 区属性 和 DC 同步。

协议访问​

协议说明文档
CoECANopen over EtherCATSDO 对象字典
CiA 402伺服驱动器状态机与使能
CiA 401通用 IO 模块数字/模拟 IO
SoEServo over EtherCATSERCOS 参数
FoEFile over EtherCAT文件传输
EoEEthernet over EtherCAT以太网隧道
AoEADS over EtherCATBeckhoff ADS
VoEVendor over EtherCAT厂商协议
FSoEFunctional Safety功能安全
MDP模块化设备模块发现

PDO 数据读写​

详细的 PDO 读写方式请参见 PDO 输入输出。

进 OP 后用 GetIO 把 packed 结构体映射到过程映像,多线程直接改字段:

#pragma pack(push, 1)
typedef struct {
uint16_t status_word;
int32_t actual_position;
} in_pdo_t;
typedef struct {
uint16_t control_word;
int32_t target_position;
} out_pdo_t;
#pragma pack(pop)

int32_t out_size = 0, in_size = 0;
uint8_t *out_ptr = NULL, *in_ptr = NULL;
uint8_t st = GetIO(master, 1, &out_size, &out_ptr, &in_size, &in_ptr);
if (ec_pdo_io_is_ok(st) && in_ptr && out_ptr
&& in_size >= (int32_t)sizeof(in_pdo_t) && out_size >= (int32_t)sizeof(out_pdo_t)) {
in_pdo_t *in = (in_pdo_t *)in_ptr;
out_pdo_t *out = (out_pdo_t *)out_ptr;
out->control_word = 0x000F;
printf("位置: %d\n", in->actual_position);
}

EMCY 紧急消息​

EtherCAT 从站在检测到异常时会发送 EMCY(Emergency)紧急消息。SDK 自动缓存从站的 EMCY 消息历史。

#pragma pack(push, 1)
typedef struct {
uint16_t error_code; /* 错误码 */
uint8_t error_register; /* 错误寄存器 */
uint8_t data[5]; /* 厂商自定义数据 */
uint16_t slave_index; /* 从站索引 */
uint32_t timestamp_ms; /* 时间戳 (毫秒) */
} ec_emcy_record_t;
#pragma pack(pop)

int EmcyGetCount(uint16_t master, uint16_t slave);
/* 调用者提供 ec_emcy_record_t 缓冲, 返回写入的记录条数 */
int EmcyGetHistory(uint16_t master, uint16_t slave,
ec_emcy_record_t* out, int max);
void EmcyClearHistory(uint16_t master, uint16_t slave);

示例:

ec_emcy_record_t hist[16];
int n = EmcyGetHistory(master, 1, hist, 16);
for (int i = 0; i < n; i++)
printf("EMCY 错误码=0x%04X 寄存器=0x%02X\n",
hist[i].error_code, hist[i].error_register);
EmcyClearHistory(master, 1);

拓扑查询​

SDK 提供从站网络拓扑的构建与查询功能,获取从站之间的父子关系和树形结构。

int TopologyBuild(uint16_t master_index, ec_topology_node_t* out_nodes, int max_nodes);
int TopologyGetRoots(uint16_t master_index, uint16_t* out_roots, int max_roots);
int TopologyGetChildren(uint16_t master_index, uint16_t parent_index,
uint16_t* out_children, int max_children);

TopologyBuild() 通常在进入 OP 状态后调用一次。TopologyGetRoots() 返回直连主站的根从站列表。

示例 — 打印拓扑树:

void print_tree(uint16_t slave_idx, int depth) {
char name[128];
GetSlaveName(master, slave_idx, name, sizeof(name));
for (int i = 0; i < depth * 2; i++) printf(" ");
printf("[%d] %s\n", slave_idx, name);

uint16_t children[64];
int n = TopologyGetChildren(master, slave_idx, children, 64);
for (int i = 0; i < n; i++)
print_tree(children[i], depth + 1);
}

ec_topology_node_t nodes[64];
TopologyBuild(master, nodes, 64);

uint16_t roots[64];
int n = TopologyGetRoots(master, roots, 64);
for (int i = 0; i < n; i++) print_tree(roots[i], 0);

子页面​

页面说明
属性与方法从站基本属性、验证、拓扑、ESI
PDO 输入输出零拷贝指针、类型化读写、批量操作
DC 同步从站级 DC 配置
事件从站状态变化、热插拔、紧急消息