跳到主要内容

C# API

Darra Profinet Slave 的 .NET 类库。程序集 DarraPnS,命名空间 DarraPnS.PnSlave。目标框架 netstandard2.0,是 6 语言 SDK 的基准实现。

using DarraPnS.PnSlave;

SDK 负责连接、启停会话、I/Q 读写。站点名、网卡、槽位由 GUI 导出运行配置,交给服务加载。周期自由配置,最低 1 ms。

推荐 — 高性能走结构体 / PDO.In·PDO.Out;快速原型走地址化 IW2 / QW0

快速开始

var dev = DarraPnS.Connect();
dev.Start();
dev.PDO.Write(ref tx); // 结构体 → I(只写)
dev.PDO.Read(ref rx); // Q → 结构体(只读)
dev.WriteInt16("IW2", 123);
short q = 0; dev.ReadInt16("QW0", out q); // 读 Q
dev.Stop();

不要 new DarraPnS(...)LoadConfig 只供配置解析 / 变量联想建表。

连接 / 启停

成员类型类别读写说明
Connect()DarraPnS设备静态本机会话
Connect(string host, int port = DefaultServicePort)DarraPnS设备静态指定本机服务。host 只应填 127.0.0.1
Start()PnSErrorCode设备启动会话;已启动则返回成功
Stop()void设备停止本会话。主站在连时不要拆应用关系。Stop 后本实例不可复用
Dispose()void设备等价 Stop + 释放(幂等)
DefaultServicePortint设备只读本机服务默认端口
IsServiceModebool设备只读是否服务会话
IsRunningbool设备只读本会话是否已成功 Start(运行态以 Connected / State 为准)

生命周期:Connect → Start → [I/Q 读写] → Stop / Dispose。数据用属性(非 GetXxx),状态返回枚举。

运行态

优先读运行态;服务不可达时见各属性说明。

成员类型类别读写说明
Connectedbool设备只读是否已与 IO 控制器建立周期数据交换
StatePnSState设备只读运行态枚举。服务不可达为 Unknown
ErrorCodePnSRuntimeErrorCode设备只读最近一次运行错误(枚举)。未识别值 Unknown
ErrorCodeRawint设备只读运行错误原值(0 = 无错误)。未识别值仍经本属性透传
ErrorMessagestring设备只读运行错误中文消息
LastServiceErrorstring设备只读最近一次服务错误(成功调用清空)

Connected == true 才表示周期数据在换。IsRunning 只说明本实例已 Start,不等于主站已连。

地址化 I / Q

西门子风格地址,公共解析器 PnSAddress.Parse 单源。字 / 双字偏移即字节偏移,不强制 2 / 4 对齐IW3 合法)。字 / 双字为大端(PROFINET 网络序)。

区域地址格式方向
I(输入面)I0.0 / IB0 / IW2 / ID4设备 → 控制器发送读回本地影子
Q(输出面)Q0.0 / QB0 / QW2 / QD4控制器 → 设备不支持NotSupported读控制器数据
dev.WriteInt16("IW2", 123);           // 写 I
short q = 0;
dev.ReadInt16("QW0", out q); // 读 Q
// dev.WriteInt16("QW0", 5); // → NotSupported
成员类型类别读写说明
WriteBool(string address, bool value)PnSErrorCodeIO写位。仅 I;写 Q 返回 NotSupported
WriteInt16(string address, short value)PnSErrorCodeIO写字(IW2,大端)。写 QW0NotSupported
WriteInt32(string address, int value)PnSErrorCodeIO写双字(ID4,大端)。写 Q → NotSupported
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,大端)

地址化读写返回 PnSErrorCode不抛出。未 Start 返回 InvalidHandle

PDO

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

方向(2026-08-22 纠正旧倒置):

调用方向读写
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 } };
dev.PDO.Write(ref tx); // 结构体 → I(只写)

PdoData rx = new PdoData();
dev.PDO.Read(ref rx); // Q → 结构体(只读)

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

In / Out

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

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

InputsMapping

将 Q 区映射为结构体快照。无 live 指针(每次从过程数据拷贝)。可选 1 ms 内部轮询 OnChanged(SDK 内部定时器)。

InputPdoInstance<PdoData> mapped = dev.PDO.InputsMapping<PdoData>();
PdoData snap = mapped.ValueSnapshot;

var watch = dev.PDO.InputsMapping<PdoData>(e =>
{
// e.Previous / e.Current / e.Timestamp
});

OutputsMapping(ref T)Write(ref T) 同义(结构体 → I)。

GetFieldAddress

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

string qAddr = dev.PDO.GetFieldAddress<PdoData>("B");                 // "QW1"
string iAddr = dev.PDO.GetFieldAddress<PdoData>("B", PnSAddressArea.Input); // "IW1"
short b;
dev.ReadInt16(qAddr, out b);
dev.WriteInt16(iAddr, 123);
成员类型类别读写说明
PDO / PdoPnSPdoPDO只读PDO 子对象(同一实例)
PDO.Write<T>(ref T data)PnSErrorCodePDO结构体 → I
PDO.Read<T>(ref T data)PnSErrorCodePDO只读Q → 结构体
PDO.OutPdoArrayInstancePDOOut[offset] 写 I
PDO.InPdoArrayInstancePDO只读In[offset] 读 Q
PDO.Outputsbyte[]PDO读写get = I 影子;set = 写 I
PDO.Inputsbyte[]PDO只读当前 Q 快照
PDO.InputsMapping<T>()InputPdoInstance<T>PDO只读Q → 结构体快照
PDO.InputsMapping<T>(onChanged)InputPdoInstance<T>PDO只读同上 + 内部 1 ms 变化回调
PDO.GetFieldAddress<T>(name)stringPDO只读字段 → Q 区地址
PDO.GetFieldAddress<T>(name, area)stringPDO只读字段 → I / Q 地址
WriteStruct<T>(ref T data)PnSErrorCodePDOPDO.Write 转发
ReadStruct<T>(ref T data)PnSErrorCodePDO只读PDO.Read 转发

失败码

两类码不要混用。

调用返回码 PnSErrorCodeStart / 地址化读写 / PDO.Read·Write 的返回值。IO 路径不抛异常。

含义
Success (0)成功
InvalidArgument地址非法 / 空缓冲
InvalidHandleStart 或已 Stop
NotConnected无 AR / 未进入数据交换
NativeError栈 / 服务端错误
LengthMismatch长度越界
NotFound地址 / 条目不存在
Busy上一次操作未完成
NotSupported写 Q 等不支持的操作
NativeDllNotFoundnative DLL 未加载
PlatformNotSupported仅 Windows x64
ServiceUnreachable服务不可达

运行态码 PnSRuntimeErrorCode(属性 ErrorCode):Ok=0 / ErrInit=-1 / ErrCfg=-2 / ErrThread=-3 / ErrRunning=-4 / ErrPdi=-5 / ErrDap=-6 / Unknown=-10000。

Connect("127.0.0.1")Start 失败时可能抛 PnSServiceException(带 PnSErrorCode + 原因)。

完整示例

using System.Runtime.InteropServices;
using DarraPnS.PnSlave;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PdoData
{
public short Status;
public short Command;
}

var dev = DarraPnS.Connect();
if (dev.Start() != PnSErrorCode.Success)
{
Console.WriteLine("启动失败: " + dev.LastServiceError);
return;
}

PdoData tx = new PdoData { Status = 123 };
dev.PDO.Write(ref tx); // 结构体 → I
dev.WriteInt16("IW2", 123); // 地址化写 I

PdoData rx = new PdoData();
dev.PDO.Read(ref rx); // Q → 结构体
short q = 0;
dev.ReadInt16("QW0", out q); // 地址化读 Q

bool onBus = dev.Connected;
PnSRuntimeErrorCode err = dev.ErrorCode;

dev.Stop();

相关