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);