跳到主要内容

PDO 输入输出

通过 slave.PDO() 访问。

PDO 周期与邮箱的关系

邮箱(SDO/CoE/FoE 等)的读取附带在 PDO 帧中,不占用额外周期时间。邮箱响应延迟约 2-3 个 PDO 周期。

出站邮箱(如 SDO 写入)由系统根据 PDO 周期自适应调度,无需用户干预。

推荐

高性能场景使用 ByteBuffer 零拷贝, 快速原型使用字节数组读写。

字节数组读写

ReadInputDataDirect / WriteOutputDataDirect

byte[] inputData = new byte[slave.Ibytes()];
slave.PDO().ReadInputDataDirect(inputData);

byte[] outputData = new byte[]{0x0F, 0x00, ...};
slave.PDO().WriteOutputDataDirect(outputData);

PDOArrayInstance 类型化访问

InputArray / OutputArray

PDO.PDOArrayInstance inputs = slave.PDO().InputArray(slave.Ibytes());
PDO.PDOArrayInstance outputs = slave.PDO().OutputArray(slave.Obytes());

// 读取
byte val = inputs.Get(0).Content();
short val16 = inputs.Get(0).AsInt16();
int val32 = inputs.Get(2).AsInt32();
float fval = inputs.Get(6).AsFloat();

// 写入
outputs.Get(0).AsInt16((short) 0x000F);
outputs.Get(2).AsInt32(100000);

PDODataItem 类型方法

  • Content() / Content(byte) — byte,1 字节
  • AsInt16() / AsInt16(short) — short,2 字节
  • AsUInt16() / AsUInt16(int) — int,2 字节
  • AsInt32() / AsInt32(int) — int,4 字节
  • AsUInt32() / AsUInt32(long) — long,4 字节
  • AsFloat() / AsFloat(float) — float,4 字节
  • AsDouble() / AsDouble(double) — double,8 字节
  • AsInt64() / AsInt64(long) — long,8 字节
  • GetBit(int bitIndex) — boolean,位读取(0-7)
  • SetBit(int bitIndex, boolean) — void,位写入(0-7)
  • AsBaseData(int dataType) — ByteBuffer,按 EtherCAT 数据类型读取

ByteBuffer 零拷贝访问

GetInputByteBuffer() / GetOutputByteBuffer()

ByteBuffer inBuf = slave.PDO().GetInputByteBuffer();
ByteBuffer outBuf = slave.PDO().GetOutputByteBuffer();

// 读取
short statusWord = inBuf.getShort(0);
int position = inBuf.getInt(2);

// 写入
outBuf.putShort(0, (short) 0x000F);
outBuf.putInt(2, 10000);

批量 PDO 读写

BatchRead(int[] offsets, int[] sizes)

ByteBuffer[] results = slave.PDO().BatchRead(
new int[]{0, 2, 6}, // 偏移
new int[]{2, 4, 4}); // 大小
short sw = results[0].getShort();
int pos = results[1].getInt();

BatchWrite(int[] offsets, byte[][] values)

int written = slave.PDO().BatchWrite(
new int[]{0, 2},
new byte[][]{{0x0F, 0x00}, {0x10, 0x27, 0x00, 0x00}});

SlavePdo 类型化读写

通过 slave.SlavePdo() 访问,提供便捷的类型化 PDO 读写:

类型化读取完整表

  • ReadInputU8(int offset) (byte,1 字节) — 读取无符号 8 位
  • ReadInputI16(int offset) (short,2 字节) — 读取有符号 16 位
  • ReadInputU16(int offset) (int,2 字节) — 读取无符号 16 位
  • ReadInputI32(int offset) (int,4 字节) — 读取有符号 32 位
  • ReadInputU32(int offset) (long,4 字节) — 读取无符号 32 位
  • ReadInputI64(int offset) (long,8 字节) — 读取有符号 64 位
  • ReadInputF32(int offset) (float,4 字节) — 读取单精度浮点
  • ReadInputF64(int offset) (double,8 字节) — 读取双精度浮点

类型化写入完整表

  • WriteOutputU8(int offset, byte val) (byte,1 字节) — 写入无符号 8 位
  • WriteOutputI16(int offset, short val) (short,2 字节) — 写入有符号 16 位
  • WriteOutputI32(int offset, int val) (int,4 字节) — 写入有符号 32 位
  • WriteOutputI64(int offset, long val) (long,8 字节) — 写入有符号 64 位
  • WriteOutputF32(int offset, float val) (float,4 字节) — 写入单精度浮点
  • WriteOutputF64(int offset, double val) (double,8 字节) — 写入双精度浮点

输入读取

SlavePdo pdo = slave.SlavePdo();
byte[] inputs = pdo.Inputs(); // 读取全部输入
byte u8 = pdo.ReadInputU8(0); // 读取 U8
short i16 = pdo.ReadInputI16(0); // 读取 I16
int u16 = pdo.ReadInputU16(0); // 读取 U16
int i32 = pdo.ReadInputI32(2); // 读取 I32
long u32 = pdo.ReadInputU32(2); // 读取 U32
float f32 = pdo.ReadInputF32(6); // 读取 Float

输出写入

SlavePdo pdo = slave.SlavePdo();
byte[] outputs = pdo.Outputs(); // 读取全部输出
pdo.Outputs(new byte[]{0x0F, 0x00}); // 写入全部输出

pdo.WriteOutputU8(0, (byte) 0x0F); // 写入 U8
pdo.WriteOutputI16(0, (short) 0x000F); // 写入 I16
pdo.WriteOutputI32(2, 100000); // 写入 I32
pdo.WriteOutputF32(6, 3.14f); // 写入 Float

ByteBuffer 零拷贝

SlavePdo pdo = slave.SlavePdo();
ByteBuffer inBuf = pdo.GetInputByteBuffer();
ByteBuffer outBuf = pdo.GetOutputByteBuffer();

InputsSliceMapping / OutputsSliceMapping(切片映射)

ByteBuffer InputsSliceMapping(int offset, int size)
ByteBuffer OutputsSliceMapping(int offset, int size)

将输入/输出 PDO 数据的指定偏移位置映射为 ByteBuffer(零拷贝)。用于 MDP 模块化设备,每个模块在过程数据中有不同偏移。

参数:

  • offset (int) -- 相对于从站输入/输出起始位置的字节偏移
  • size (int) -- 切片大小(字节数)

示例:

SlavePdo pdo = slave.SlavePdo();

// MDP 设备: 模块1 从偏移 0 开始(8字节),模块2 从偏移 8 开始(4字节)
ByteBuffer mod1 = pdo.InputsSliceMapping(0, 8);
ByteBuffer mod2 = pdo.InputsSliceMapping(8, 4);

// 读取模块1 的数据
short statusWord = mod1.getShort(0);
int position = mod1.getInt(2);

// 写入输出切片
ByteBuffer outSlice = pdo.OutputsSliceMapping(0, 2);
outSlice.putShort(0, (short) 0x000F);

InputsSliceMapping 回调(MDP 模块变化监听)

SlavePdo pdo = slave.SlavePdo();

// 监控 MDP 模块2(偏移 8 字节,4 字节)的输入数据变化
ByteBuffer mod2 = pdo.InputsSliceMapping(8, 4);
// 在 InputDataChanged 事件中读取切片数据
master.Events().addInputDataChangedListener((mi, si) -> {
if (si == slave.SlaveNum()) {
short val = mod2.getShort(0);
System.out.println("模块2 数据: " + val);
}
});

完整示例

Slave slave = master.getSlave(1);

// ===== ByteBuffer 零拷贝 =====
ByteBuffer inBuf = slave.PDO().GetInputByteBuffer();
ByteBuffer outBuf = slave.PDO().GetOutputByteBuffer();
short statusWord = inBuf.getShort(0);
outBuf.putShort(0, (short) 0x000F);

// ===== 字节数组 =====
byte[] inputData = new byte[slave.Ibytes()];
slave.PDO().ReadInputDataDirect(inputData);

// ===== PDOArrayInstance =====
PDO.PDOArrayInstance in = slave.PDO().InputArray(slave.Ibytes());
PDO.PDOArrayInstance out = slave.PDO().OutputArray(slave.Obytes());
int pos = in.Get(2).AsInt32();
out.Get(0).AsInt16((short) 0x000F);