跳到主要内容

PDO 输入输出

PDO(Process Data Object)过程数据的读写方式汇总。所有方法通过 slave.PDO 访问。

PDO 周期与邮箱的关系

邮箱(SDO/CoE/FoE 等)的入站读取通过 Piggyback 机制附带在 PDO 帧中,不占用额外周期时间

每个 PDO 周期的 LRW 帧自动携带 mbxstatus。当检测到从站有待读邮箱时,下一周期的 PDO 帧附带 FPRD 数据报读取邮箱内容(与 DC FRMW 相同方式)。邮箱响应延迟约 2 个 PDO 周期。

出站邮箱(如 SDO 写入)仍为独立帧,系统根据 PDO 周期自适应调度:

PDO 周期出站邮箱策略说明
高速 (<2ms)降频处理,每 ~5ms 处理一次避免阻塞帧拉长 PDO 周期
正常 (2-10ms)每周期处理每周期 1-4 条出站邮箱操作
慢速 (>10ms)每周期批量处理充分利用富余时间
推荐

高性能场景使用 结构体映射(零拷贝),快速原型使用 索引访问

结构体映射(零拷贝)

InputsMapping<T>()

public ref T InputsMapping<T>() where T : struct

将输入 PDO 数据映射为结构体引用(零拷贝,约 5-10 纳秒)。

说明: 结构体大小必须与 Ibytes 完全匹配。返回的引用直接指向 IOmap 内存。

示例:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ServoInput
{
public ushort StatusWord;
public int ActualPosition;
public int ActualVelocity;
}

ref ServoInput input = ref slave.PDO.InputsMapping<ServoInput>();
Console.WriteLine($"当前位置: {input.ActualPosition}");

InputsMapping<T>(onChanged)

public InputPdoInstance<T> InputsMapping<T>(Action<PdoStructChangedEventArgs<T>>? onChanged = null) where T : struct
public InputPdoInstance<T> InputsMapping<T>(Action onChanged) where T : struct

将输入 PDO 数据映射为结构体实例,支持数据变化回调。

返回值: InputPdoInstance<T> — 通过 .Value 获取当前输入 PDO 结构体引用(零拷贝)。

回调参数:

public sealed class PdoStructChangedEventArgs<T> : EventArgs where T : struct
{
public ushort SlaveIndex { get; } // 从站索引
public bool IsInput { get; } // 是否为输入PDO
public T Previous { get; } // 变化前的值
public T Current { get; } // 变化后的值
public DateTime Timestamp { get; } // 时间戳
}

示例:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ServoInput
{
public ushort StatusWord;
public int ActualPosition;
public int ActualVelocity;
}

var inputInstance = slave.PDO.InputsMapping<ServoInput>(e =>
{
Console.WriteLine($"位置变化: {e.Previous.ActualPosition} -> {e.Current.ActualPosition}");
});

ref ServoInput input = ref inputInstance.Value;

InputsSliceMapping<T>(int offset)

public ref T InputsSliceMapping<T>(int offset) where T : struct

将输入 PDO 数据的指定偏移位置映射为结构体引用。用于模块化设备。

OutputsMapping<T>()

public ref T OutputsMapping<T>() where T : struct

将输出 PDO 数据映射为结构体引用(零拷贝)。结构体大小必须与 Obytes 匹配。

示例:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ServoOutput
{
public ushort ControlWord;
public int TargetPosition;
public int TargetVelocity;
}

ref ServoOutput output = ref slave.PDO.OutputsMapping<ServoOutput>();
output.ControlWord = 0x000F;
output.TargetPosition = 10000;

OutputsSliceMapping<T>(int offset)

public ref T OutputsSliceMapping<T>(int offset) where T : struct

将输出 PDO 数据的指定偏移位置映射为结构体引用。

BindPdoStruct<T>(...)

public PdoStructBinding<T> BindPdoStruct<T>(
PDOManager manager, bool isInput,
int offset = 0, Func<T, T, bool>? comparer = null) where T : struct

绑定 PDO 结构体变化事件(基于 PDOManager 的数据变化通知)。

参数:

  • manager — PDOManager 实例
  • isInput — true=输入(TxPDO), false=输出(RxPDO)
  • offset — 结构体在 IOmap 中的偏移字节
  • comparer — 可选的自定义比较器

字节数组访问

Inputs / Outputs

public byte[] Inputs { get; }
public byte[] Outputs { get; set; }

直接读写 PDO 字节数组。每次访问从 IOmap 读取最新数据。写入 Outputs 时数据长度必须与 Obytes 匹配。

In / Out(索引访问)

public PDOArrayInstance In { get; }
public PDOArrayInstance Out { get; }

基于数组的 PDO 实例,支持按索引访问。

示例:

var value = slave.PDO.In[0].Content;    // 读取第一个输入 PDO
slave.PDO.Out[0].Content = 0xFF; // 写入第一个输出 PDO