从站 API
所有从站函数使用 uint16_t master_index 和 uint16_t slave_index(1-based)参数。
快速开始
#define DYNAMIC_LOAD
#include "ethercat.h"
dll_t dll;
LOAD_DLL(&dll, "Darra.Core.dll");
uint16_t master = dll.Initialize();
uint16_t count = dll.SetNetwork(master, "\\Device\\NPF_{GUID}", "");
printf("从站总数: %u\n", count);
/* 读取从站信息 (slave_index 1-based) */
char name[128];
dll.GetSlaveName(master, 1, name, sizeof(name));
uint32_t vid = dll.GetSlaveVendorId(master, 1);
uint32_t pid = dll.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];
dll.GetSlaveName(master, 1, name, sizeof(name));
/* 默认组从站数 */
uint16_t group_count = dll.GetGroupSlaveCount(master, 0);
提示
组相关函数详见 从站分组。
地址与标识
/* 物理配置地址(自动分配) */
uint16_t addr = dll.GetSlaveConfigAddr(master, 1); /* 如 0x1001 */
uint16_t alias = dll.GetSlaveAliasAddr(master, 1); /* EEPROM 别名 */
/* 标识 */
char name[128];
dll.GetSlaveName(master, 1, name, sizeof(name));
uint32_t vid = dll.GetSlaveVendorId(master, 1);
uint32_t pid = dll.GetSlaveProductCode(master, 1);
uint32_t rev = dll.GetSlaveRevision(master, 1);
uint32_t sn = dll.GetSlaveSerialNumber(master, 1);
IO 区与邮箱属性
/* PDO 区位数 / 字节数 / IOmap 偏移 / 起始位 */
uint16_t in_bits = dll.GetSlaveInputBits(master, 1);
uint32_t in_bytes = dll.GetSlaveInputBytes(master, 1);
uint32_t in_off = dll.GetSlaveInputOffset(master, 1);
uint8_t in_sbit = dll.GetSlaveInputStartBit(master, 1);
uint16_t out_bits = dll.GetSlaveOutputBits(master, 1);
uint32_t out_bytes = dll.GetSlaveOutputBytes(master, 1);
uint32_t out_off = dll.GetSlaveOutputOffset(master, 1);
uint8_t out_sbit = dll.GetSlaveOutputStartBit(master, 1);
/* DC 状态与时间 */
BOOL has_dc = dll.GetSlaveHasDC(master, 1);
int32_t cycle0 = dll.GetSlaveDCCycle0(master, 1);
int32_t shift = dll.GetSlaveDCShift(master, 1);
int32_t pd = dll.GetSlavePropagationDelay(master, 1);
/* 邮箱协议与缓冲区 */
uint16_t mbx_proto = dll.GetSlaveMailboxProto(master, 1);
uint16_t mbx_wr_len = dll.GetSlaveMailboxWriteLength(master, 1);
uint16_t mbx_rd_len = dll.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 输入输出。
/* 读取输入 PDO (offset 为字节偏移) */
uint16_t status_word = PDOReadInputU16(master, slave, 0);
int32_t actual_pos = PDOReadInputI32(master, slave, 2);
float temp = PDOReadInputF32(master, slave, 6);
/* 写入输出 PDO */
PDOWriteOutputU16(master, slave, 0, 0x000F); /* ControlWord */
PDOWriteOutputI32(master, slave, 2, 100000); /* TargetPosition */
PDOWriteOutputF32(master, slave, 6, 3.14f);
支持的类型: U8/I8、U16/I16、U32/I32、U64/I64、F32/F64。
EMCY 紧急消息
EtherCAT 从站在检测到异常时会发送 EMCY(Emergency)紧急消息。SDK 自动缓存从站的 EMCY 消息历史。
typedef struct {
uint16_t error_code;
uint8_t error_register;
uint8_t data[5];
} ec_emcy_t;
int EmcyGetCount(uint16_t master, uint16_t slave);
ec_emcy_t* EmcyGetHistory(uint16_t master, uint16_t slave, int* count);
void EmcyClearHistory(uint16_t master, uint16_t slave);
示例:
int n;
ec_emcy_t* hist = EmcyGetHistory(master, 1, &n);
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* nodes, int max_nodes);
int TopologyGetRoots(uint16_t master_index, uint16_t* roots, int max_roots);
int TopologyGetChildren(uint16_t master_index, uint16_t parent_slave,
uint16_t* children, int max_children);
TopologyBuild() 通常在进入 OP 状态后调用一次。TopologyGetRoots() 返回直连主站的根从站列表。
示例 — 打印拓扑树:
void print_tree(uint16_t slave_idx, int depth) {
char name[128];
dll.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 = dll.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];
dll.TopologyBuild(master, nodes, 64);
uint16_t roots[64];
int n = dll.TopologyGetRoots(master, roots, 64);
for (int i = 0; i < n; i++) print_tree(roots[i], 0);
子页面
| 页面 | 说明 |
|---|---|
| 属性与方法 | 从站基本属性、验证、拓扑、ESI |
| PDO 输入输出 | 零拷贝指针、类型化读写、批量操作 |
| DC 同步 | 从站级 DC 配置 |
| 事件 | 从站状态变化、热插拔、紧急消息 |