跳到主要内容

MDP — 模块化设备

Modular Device Profile (MDP) 是 EtherCAT 中描述模块化设备的标准协议。

通过 slave.GetMDP() 获取 MDP& 引用。从站不支持 MDP 时返回的引用 IsSupported()false

自动处理

内部会自动处理 MDP 设备的模块检测和 PDO 配置。 绝大多数场景下, 用户无需直接操作 MDP。

关于热插拔

SDK 支持 MDP 模块热插拔再配置自修复。 但生产环境中几乎不会出现 MDP 模块热插拔的使用场景。 EtherCAT 从站的模块配置在设备上电后即固定, 运行期间不会动态变更。 部署 MDP 模块化设备推荐使用 DENI; 如需自动配置, 请先导入对应的 ESI 文件, 再调用 AutoStartup()

属性

ConfiguredModules()

std::vector<MdpSlotInfo> ConfiguredModules() const;

已配置模块列表。每次访问实时通过 CoE 读取 (索引 0xF030), 非可用状态自动切换。

返回值:

  • std::vector<MdpSlotInfo> — 已配置模块列表

相关结构:

struct MdpSlotInfo {
int SlotIndex; // 槽位索引 (从 1 开始)
uint32_t ModuleIdent; // 模块标识码 (32 位)
std::string ModuleName; // 模块名称
uint32_t ModuleType; // 模块设备类型码
std::string Status; // 状态 ("已配置" / "已检测")
uint16_t ObjectDictionaryIndex; // 对象字典基地址
std::string ModuleIOType; // I/O 类型 (Input / Output / I/O / Unknown)
};
ModuleIOType 判定逻辑

优先从 ESI 文件的模块定义中读取 TxPdo / RxPdo 配置:

  • 仅有 TxPdo -> "Input" (从站发送到主站)
  • 仅有 RxPdo -> "Output" (主站发送到从站)
  • 两者都有 -> "I/O"

ESI 无法判断时回退到模块名称关键字匹配。

示例:

auto& mdp = slave.GetMDP();
for (auto& slot : mdp.ConfiguredModules()) {
printf("Slot %d: %s (0x%08X)\n",
slot.SlotIndex, slot.ModuleName.c_str(), slot.ModuleIdent);
}

DetectedModules()

std::vector<MdpSlotInfo> DetectedModules() const;

已检测模块列表, 反映物理上实际插入的模块。每次访问实时通过 CoE 读取 (索引 0xF050), 非可用状态自动切换。

返回值:

  • std::vector<MdpSlotInfo> — 已检测模块列表 (同 ConfiguredModules 结构)

示例:

for (auto& slot : slave.GetMDP().DetectedModules()) {
printf("Slot %d: %s\n", slot.SlotIndex, slot.ModuleName.c_str());
}

AvailableModules()

std::vector<MdpAvailableModule> AvailableModules() const;

ESI 中定义的可选模块列表。需要从站已导入 ESI 文件, 否则返回空向量。结果会缓存, 仅首次访问时解析。

返回值:

  • std::vector<MdpAvailableModule> — 可选模块列表

相关结构:

struct MdpAvailableModule {
uint32_t ModuleIdent; // 模块标识码
uint32_t ModuleType; // 模块设备类型码
std::string ModuleName; // 模块名称
std::string Description; // 模块描述
};

示例:

for (auto& mod : slave.GetMDP().AvailableModules()) {
printf("%s (0x%08X)\n", mod.ModuleName.c_str(), mod.ModuleIdent);
}

方法

GetModulePdoLayout()

std::optional<std::vector<MdpModulePdoInfo>> GetModulePdoLayout() const;

获取各模块在从站 IOmap 中的 PDO 布局。通过 CoE SDORead 读取 PDO Assignment (0x1C12/0x1C13) 和 PDO Mapping 条目, 累积计算各模块的字节偏移。

备注

需要从站已完成 DENI 配置 (ConfigMap 后可用), 不依赖 ESI 文件。CoE 不可用或未检测到模块时返回 std::nullopt

返回值:

  • std::optional<std::vector<MdpModulePdoInfo>> — 各模块的 PDO 布局信息, 无法获取时返回 std::nullopt

相关结构:

struct MdpModulePdoInfo {
int SlotIndex; // 槽位索引
uint32_t InputOffset; // 输入 PDO 偏移 (相对于 slave.Ioffset)
uint16_t InputSize; // 输入 PDO 字节数
uint32_t OutputOffset; // 输出 PDO 偏移 (相对于 slave.Ooffset)
uint16_t OutputSize; // 输出 PDO 字节数
};

示例:

auto layout = slave.GetMDP().GetModulePdoLayout();
if (layout) {
for (auto& mod : *layout) {
printf("Slot %d: In=%uB @%u, Out=%uB @%u\n",
mod.SlotIndex, mod.InputSize, mod.InputOffset,
mod.OutputSize, mod.OutputOffset);
}
}

自动配置

MDP 设备的自动配置需要先导入对应的 ESI 文件, 由以下方法完成:

  • 导入 ESI (主站)master.SetEsiFile() / master.SetEsiFiles()
  • 自动配置 (主站)master.EnableAutoStartup()
  • 导入 ESI (从站)slave.SetEsiFile()
  • 自动配置 (从站)slave.AutoStartup()