从站 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);
协议访问
| 协议 | 说明 | 文档 |
|---|---|---|
| CoE | CANopen over EtherCAT | SDO 对象字典 |
| CiA 402 | 伺服驱动器 | 状态机与使能 |
| CiA 401 | 通用 IO 模块 | 数字/模拟 IO |
| SoE | Servo over EtherCAT | SERCOS 参数 |
| FoE | File over EtherCAT | 文件传输 |
| EoE | Ethernet over EtherCAT | 以太网隧道 |
| AoE | ADS over EtherCAT | Beckhoff ADS |
| VoE | Vendor over EtherCAT | 厂商协议 |
| FSoE | Functional 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 配置 |
| 事件 | 从站状态变化、热插拔、紧急消息 |