跳到主要内容

过程数据

先确认 诊断ConnectedIoStatus 正常,再读写过程数据。

数据获取用属性或返回错误码的方法,IO 路径不抛异常(未启动返回 InvalidHandle)。地址由公共解析器 PnSAddress.Parse 单源解析。

地址

西门子风格。字 / 双字偏移即字节偏移,不强制 2 / 4 对齐IW3 合法)。字 / 双字为大端(PROFINET 网络序)。

区域地址格式方向
I(输入面)I0.0 / IB0 / IW2 / ID4设备 → 控制器发送读回本地影子
Q(输出面)Q0.0 / QB0 / QW2 / QD4控制器 → 设备返回 NotSupported读控制器数据
MM0.0 / MB0 / MW0 / MD0内部存储(映射输入面)本机可见本机可见
DBDB1.DBX0.0 / DB1.DBB2 / DBW0 / DBD4 / DB1.0槽位 1 数据块按区按区

服务会话是单一线性过程区:仅 DB1 有效,槽位大于 1 返回 NotFound

地址化读写

成员类型类别读写说明
WriteBool(string address, bool value)PnSErrorCodeIO写位。仅 I / M / DB;写 Q 返回 NotSupported
WriteInt16(string address, short value)PnSErrorCodeIO写字(IW2,大端)
WriteInt32(string address, int value)PnSErrorCodeIO写双字(ID4,大端)
ReadBool(string address, out bool value)PnSErrorCodeIO只读读位(I 影子 / Q 控制器值)
ReadInt16(string address, out short value)PnSErrorCodeIO只读读字(IW2 / QW0,大端)
ReadInt32(string address, out int value)PnSErrorCodeIO只读读双字(ID4 / QD4,大端)
ReadArea(PnSAddressArea area, out byte[] data)PnSErrorCodeIO只读整区快照。Input / Output / Memory
WriteArea(PnSAddressArea area, byte[] data)PnSErrorCodeIO整区写入。长度必须等于区长度。写 Q 返回 NotSupported
Read(out byte[] fromPlc)PnSErrorCodeIO只读读当前 Q 区快照
Write(byte[] toPlc)PnSErrorCodeIO从偏移 0 写 I 区(允许短写)
this[int offset]byteIO读写get = 读 Q 绝对字节;set = 写 I 绝对字节。失败抛异常
device.WriteInt16("IW2", 123);
short q = 0;
PnSErrorCode rc = device.ReadInt16("QW0", out q);
if (rc != PnSErrorCode.Success)
Console.WriteLine(rc);

// device.WriteInt16("QW0", 5); // → NotSupported

ReadArea / WriteArea 一次整区,避免逐地址往返。WriteAreadata 长度必须与区长度一致,否则 LengthMismatch

过程数据质量

读写之前先看 IoStatus。GOOD / BAD 语义、AllGood 等见 诊断 · 过程数据质量

if (!device.IoStatus.InputDataGood)
Console.WriteLine("控制器数据当前不可用,先不要当有效值用");

辅助:结构体映射

辅助写法。 主路径是诊断 + 地址化 I / Q。结构体映射只是把同一过程区按字段排开,不是永久主叙事。

通过 device.PDO 访问(Pdo 是同一实例)。与地址化读写同源同区。

调用方向读写
PDO.Write(ref tx)结构体 → I(设备 → 控制器)只写
PDO.Read(ref rx)Q → 结构体(控制器 → 设备)只读
PDO.Out[i]写 I 字节可写
PDO.In[i]读 Q 字节只读
PDO.Outputsget = I 影子;set = 整段写 I读写
PDO.Inputs当前 Q 快照(每次新拷)只读

结构体必须 [StructLayout(LayoutKind.Sequential, Pack = 1)]。字段按声明顺序紧排;bool 占 1 字节;字 / 双字 / 8 字节大端。支持数值、bool、枚举、定长 byte[]MarshalAs(ByValArray, SizeConst=N))、嵌套结构体。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PdoData
{
public byte A; // 偏移 0
public short B; // 偏移 1(大端)
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] D; // 偏移 3
}

PdoData tx = new PdoData { A = 1, B = -2, D = new byte[] { 9, 8, 7, 6 } };
device.PDO.Write(ref tx);

PdoData rx = new PdoData();
device.PDO.Read(ref rx);

也可 device.WriteStruct(ref tx) / device.ReadStruct(ref rx),与上同义。

byte q0 = device.PDO.In[0].Content;     // 读 Q
device.PDO.Out[0].Content = 0x11; // 写 I
short iw = device.PDO.Out[2].AsInt16; // 大端字
// device.PDO.In[0].Content = 1; // 抛 InvalidOperationException(In 只读)

In[i] / Out[i]i 是过程映像字节偏移。PdoDataItem 另有 AsUInt16 / AsInt32 / AsFloat / GetBit / SetBitSetBit 仅 Out)。

InputsMapping<T>() 把 Q 区映射为结构体快照(每次拷贝,无 live 指针)。可选内部轮询 OnChangedOutputsMapping(ref T)Write(ref T) 同义。

GetFieldAddress 把字段名翻成 I / Q 地址,供地址化读写按字段访问。无参重载默认 Q(与 Read 同向)。

string qAddr = device.PDO.GetFieldAddress<PdoData>("B");                      // "QW1"
string iAddr = device.PDO.GetFieldAddress<PdoData>("B", PnSAddressArea.Input); // "IW1"
成员类型类别读写说明
PDO / PdoPnSPdo辅助只读同一实例
PDO.Write<T>(ref T data)PnSErrorCode辅助结构体 → I
PDO.Read<T>(ref T data)PnSErrorCode辅助只读Q → 结构体
PDO.OutPdoArrayInstance辅助Out[offset] 写 I
PDO.InPdoArrayInstance辅助只读In[offset] 读 Q
PDO.Outputsbyte[]辅助读写get = I 影子;set = 写 I
PDO.Inputsbyte[]辅助只读当前 Q 快照
PDO.InputsMapping<T>()InputPdoInstance<T>辅助只读Q → 结构体快照
PDO.GetFieldAddress<T>(name)string辅助只读字段 → Q 区地址
WriteStruct<T>(ref T data)PnSErrorCode辅助PDO.Write 转发
ReadStruct<T>(ref T data)PnSErrorCode辅助只读PDO.Read 转发