跳到主要内容

初始化与构造

推荐方式

强烈建议使用 Darra 配置工具导出的 DENI 文件进行初始化。DENI 文件包含完整的网络配置 (网口、从站、PDO 映射、DC 设置等), 可确保配置的一致性和正确性。

构造函数​

EtherCATMaster(dll)​

explicit EtherCATMaster(dll_t& dll);

创建主站实例。需要随后调用 SetNetwork() 和 Build() 完成初始化。

示例:

using namespace darra;
EtherCATMaster master(dll);

Builder 模式初始化 (推荐)​

EtherCATMaster 支持链式 Builder 模式, 通过 SetNetwork、SetENI、EnableAutoStartup 配置后调用 Build 完成初始化。

EtherCATMaster master(dll);
bool ok = master.SetNetwork("\\Device\\NPF_{...}")
.SetENI("C:/EtherCAT/config.deni")
.Build();

SetNetwork()​

EtherCATMaster& SetNetwork(const std::string& primary, const std::string& redundant = "");

设置主网口和可选的冗余网口。返回自身引用支持链式调用。

SetENI()​

EtherCATMaster& SetENI(const std::string& path);

登记 ENI / DENI 配置文件路径。Build() 读取文件后交给 LoadConfigJson。返回自身引用支持链式调用。

用户加载路径:SetENI / LoadConfigJson / LoadDeniFile / LoadEniFile。不要调用 SaveXMLConfiguration / LoadAndApplyXMLConfiguration(非用户 API)。详见 ENI 配置。

LoadConfigJson()​

int DarraEcat_LoadConfigJson(uint16_t masterIndex, const char* jsonOrXml);
int darra::ethercat::master_other::load_config_json(
EtherCATMaster& m, const std::string& json);

原生配置引擎。接受 JSON 或 DENI/ENI XML 文本。SetENI + Build() 内部走此入口。返回值 < 0 失败。

示例:

int rc = darra::ethercat::master_other::load_config_json(master, xmlText);
if (rc < 0) return -1;

EnableAutoStartup()​

EtherCATMaster& EnableAutoStartup();

标记需要自动配置从站。返回自身引用支持链式调用。

备注

如果使用 ENI / DENI 文件, 通常不需要调用此方法。已有启动参数的从站会被完整跳过, 不会被覆盖或补充。此方法仅对未配置的从站生效 (自动从 ESI / MDP / SM 生成 PDO / DC / 启动参数)。

仅 MasterBuilder 路径消费此标记

MasterBuilder::Build() 会在构建时执行自动配置;EtherCATMaster::Build() 当前不消费此标记, 需要自动配置时改用 MasterBuilder, 或手动调用 master_other::auto_configure_sm(m, 0)。

Validate()​

ValidationResult Validate() const;

Build 前配置预检查, 不执行实际初始化。返回验证结果, 包含是否通过和错误列表。

相关结构:

struct ValidationResult {
bool IsValid; // 验证是否通过
std::vector<std::string> Errors; // 验证错误列表 (通过时为空)
};

示例:

auto result = master.Validate();
if (!result.IsValid) {
for (auto& err : result.Errors) printf("验证错误: %s\n", err.c_str());
return -1;
}
master.Build();

Build()​

bool Build();

构建并初始化主站。返回 bool 表示是否成功。失败后可读 LastError() 取错误码(2=驱动未安装 / 21=瞬态未就绪 / 1168=未绑定 / 170=旧 owner 未释放)。

示例:

EtherCATMaster master(dll);
bool ok = master.SetNetwork("\\Device\\NPF_{...}")
.SetENI("C:/EtherCAT/config.deni")
.EnableAutoStartup()
.Build();

静态工厂方法​

EtherCATMaster_FromJson()​

namespace darra::ethercat {
EtherCATMaster EtherCATMaster_FromJson(dll_t& dll, const std::string& json_config);
}

通过 JSON 配置字符串一步初始化。失败抛出 DarraException。

EtherCATMaster_FromJsonFile()​

namespace darra::ethercat {
EtherCATMaster EtherCATMaster_FromJsonFile(dll_t& dll, const std::string& path);
}

通过 JSON 文件一步初始化。失败抛出 DarraException。

InitializeSpecificMaster()​

static std::optional<EtherCATMaster> InitializeSpecificMaster(dll_t& dll, uint16_t masterIndex);

初始化指定索引的主站。与 Build() 不同, 此方法指定主站编号而非自动分配 (不允许 0)。失败返回 std::nullopt。

独立 MasterBuilder 类​

namespace darra::ethercat {
class MasterBuilder {
public:
explicit MasterBuilder(dll_t& dll);
MasterBuilder& SetNetwork(const std::string& primary, const std::string& secondary = "");
MasterBuilder& SetENI(const std::string& path);
MasterBuilder& SetEsiFiles(const std::string& path);
MasterBuilder& EnableAutoStartup();
MasterBuilder& SetRevisionMatch(ScanRevisionMatchMode mode);
BuildResult Build();
};
}

返回 BuildResult 结构体的独立 Builder。

相关结构:

struct BuildResult {
bool Success; // 是否成功
std::string Message; // 描述消息
uint16_t MasterIndex; // 成功时为有效索引, 失败时为 0xFFFF
};

示例:

using namespace darra::ethercat;

auto result = MasterBuilder(dll)
.SetNetwork("\\Device\\NPF_{...}")
.SetENI("config.xml")
.Build();

if (result.Success) printf("主站索引: %d\n", result.MasterIndex);

RAII 生命周期​

EtherCATMaster 遵循 RAII 原则: Build() 创建主站, 析构时自动释放。无需手动调用 Dispose()。

{
EtherCATMaster master(dll);
master.SetNetwork("\\Device\\NPF_{...}");
master.Build();
master.SetState(EcState::OP);
master.Start();
} // 离开作用域, 析构自动 Dispose

Dispose()​

void Dispose();

手动释放主站资源。析构函数会自动调用, 通常无需手动调用。

EmergencyCleanup() (静态)​

static void EmergencyCleanup(dll_t& dll);

紧急清理所有主站资源, 释放网卡句柄。在进程异常退出或信号处理中调用。

移动语义​

EtherCATMaster 支持移动构造, 但禁止拷贝, 确保资源唯一所有权。

EtherCATMaster master1(dll);
EtherCATMaster master2 = std::move(master1);
// master1 现在无效, master2 拥有资源

容器存储:

auto master = std::make_unique<EtherCATMaster>(dll);
master->SetNetwork("\\Device\\NPF_{...}");
master->Build();

多实例管理​

每个 EtherCATMaster 实例管理一条独立的 EtherCAT 总线, 使用不同的网卡。创建新实例无需重启, 即时生效。

ActiveInstanceCount() / MaxInstanceCount()​

static int ActiveInstanceCount();
static int MaxInstanceCount(dll_t& dll);

查询当前活跃的主站实例数量和允许的最大主站实例数量。

示例:

EtherCATMaster master1(dll);
master1.SetNetwork(adapters[0].name);
master1.EnableAutoStartup();
master1.Build();

EtherCATMaster master2(dll);
master2.SetNetwork(adapters[1].name);
master2.EnableAutoStartup();
master2.Build();

printf("活跃主站数: %d\n", EtherCATMaster::ActiveInstanceCount());
多实例要求
  • 每个实例必须使用不同的网卡 — 同一网卡不能被多个实例同时使用
  • CPU 核心自动分配 — 每个实例自动占用不同的 CPU 核心
  • Mailbox Gateway 端口自动偏移 — 每个实例自动分配不同的端口号
  • 授权与日志共享 — 所有实例共享同一授权状态和日志系统

网络扫描​

网卡枚举范围

默认只列出已绑定 DarraRT_Eth 的物理有线口。虚拟网卡、WiFi、TAP 不进列表。ASIX 等 USB 有线网卡按物理有线口保留。未绑定口不要当作主口候选(见 boundProtocol)。

GetAvailableNetworks()​

namespace darra::ethercat {
std::vector<AvailableNetworkInfo> GetAvailableNetworks(dll_t& dll,
bool isRedundant = false,
bool needSlaveCount = false);
}

获取网卡列表。默认只含已绑定的物理有线口。

相关结构:

struct AvailableNetworkInfo {
std::string name; // 网卡标识 (如 \\Device\\NPF_{...})
std::string desc; // 网卡描述
int slaveCount = 0; // 扫描到的从站数量 (仅 needSlaveCount=true 时有效)
int boundProtocol = 0; // 是否已绑定 DarraRT_Eth (1=已绑定, 0=未绑定)
};

示例:

using namespace darra::ethercat;
auto adapters = GetAvailableNetworks(dll, false, true);
for (const auto& a : adapters) printf("%s: %d 个从站\n", a.desc.c_str(), a.slaveCount);

Scan() / ConfigMap()​

namespace darra::ethercat {
int Scan(EtherCATMaster& m, ScanRevisionMatchMode revisionMatch = ScanRevisionMatchMode::IgnoreRevision);
int ConfigMap(EtherCATMaster& m);
int ConfigMapGroup(EtherCATMaster& m, uint8_t group);
}

扫描从站、配置 IOmap、按组配置 IOmap。

完整示例​

#include "ethercat.hpp"
using namespace darra;
using namespace darra::ethercat;

int main() {
try {
EtherCATMaster master(dll);
master.SetENI("C:/EtherCAT/MyProject.deni").Build();

master.SetState(EcState::OP);
master.Start();

printf("主站 %d: %d 个从站\n", master.MasterNumber(), master.SlaveCount());
getchar();
} catch (const DarraException& e) {
printf("错误: %s\n", e.what());
return -1;
}
return 0;
}