跳到主要内容

设备 API 结构

PROFINET IO Device 的 C 入口,用来启动设备、写 Q / 读 I、看运行态和诊断。句柄是 pns_service_handle_t

本 SDK 只做 PROFINET IO Device,不提供其它现场总线协议的入口。

API 结构

静态 pns_* 不必会话。会话函数第一个参数是 session。诊断函数编成一组,对应 C# device.Diagnostics

static
├── pns_is_service_ready / pns_service_connected / pns_service_state
├── pns_service_wait_reason / pns_service_status_message
└── pns_last_error / pns_last_error_code / pns_runtime_error_message

pns_service_handle_t session

├── PnSServiceConnectRealtime / PnSServiceStart / PnSServiceStop / PnSServiceClose

├── 过程数据 In(读 I,模块输入,只读)
│ ├── PnSProcessDataInputsMapping / PnSProcessDataInputsMappingRO // 0 拷贝:映射一次,字段自己变(I 只读;RO = 只读视图)
│ ├── PnSProcessDataInI8 / PnSProcessDataInU8 / PnSProcessDataInI16 / PnSProcessDataInU16
│ ├── PnSProcessDataInI32 / PnSProcessDataInU32 / PnSProcessDataInI64 / PnSProcessDataInU64
│ ├── PnSProcessDataInF32 / PnSProcessDataInF64
│ ├── PnSProcessDataInBool / PnSProcessDataInBit
│ ├── PnSProcessDataReadStruct / PnSProcessDataCopyInputsTo // 快照
│ └── PnSServiceRead / ReadArea / ReadBool / ReadInt16 / ReadInt32
├── 过程数据 Out(写 Q,模块输出,可写)
│ ├── PnSProcessDataOutputsMapping // 0 拷贝:改字节即改过程映像
│ ├── PnSProcessDataOutI8 / PnSProcessDataOutU8 / PnSProcessDataOutI16 / PnSProcessDataOutU16
│ ├── PnSProcessDataOutI32 / PnSProcessDataOutU32 / PnSProcessDataOutI64 / PnSProcessDataOutU64
│ ├── PnSProcessDataOutF32 / PnSProcessDataOutF64
│ ├── PnSProcessDataOutBool / PnSProcessDataOutBit
│ ├── PnSProcessDataWriteStruct / PnSProcessDataCopyToOutputs // 快照
│ └── PnSServiceWrite / WriteArea / WriteBool / WriteInt16 / WriteInt32

├── 事件
│ ├── PnSServiceOnConnectedChanged
│ ├── PnSServiceOnStateChanged
│ ├── PnSServiceOnErrorOccurred
│ └── PnSServiceOnLogged

├── PnSServiceIsConnected / GetState / GetWaitReason / GetEverConnected / GetErrorCode

├── 诊断(对应 C# device.Diagnostics)
│ ├── PnSServiceGetDiag
│ ├── PnSServiceGetIoStatus
│ ├── PnSServiceGetAlarms / GetAlarmHistory
│ └── PnSServiceGetRecords

└── PnSServiceGetIm

写 Q(模块输出,设备 → 控制器),读 I(模块输入,控制器 → 设备)。

用法

启停

#include "pns.h"

pns_service_handle_t session = NULL;
if (PnSServiceConnectRealtime(&session) != PNS_OK)
return 1;
if (PnSServiceStart(session) != PNS_OK)
return 1;

while (running)
{
if (!PnSServiceIsConnected(session))
{
/* PnSServiceGetWaitReason(session) */
continue;
}
PnSServiceWriteBool(session, "Q0.0", true); /* 写 Q */
{
bool from_plc = false;
PnSServiceReadBool(session, "I0.0", &from_plc); /* 读 I */
}
}

PnSServiceStop(session);
PnSServiceClose(session);

看状态不必建会话:pns_is_service_ready / pns_service_connected / pns_service_wait_reason

过程数据

方式访问说明
过程数据PnSProcessDataInputsMapping / PnSProcessDataInputsMappingRO / PnSProcessDataOutputsMapping0 拷贝:映射一次(I 只读视图用 RO)
过程数据PnSProcessDataIn* / PnSProcessDataOut*快照 / 类型化偏移

标识

PnSServiceGetImpns_service_im_info_t。I&M1–I&M3 已由原生栈启用并如实回读,I&M4 未启用。字段缺失保持空,不虚构;主站没写过时读到的是栈的出厂占位值,不是空串。

字段说明
station_name站点名
vendor_id厂商 ID
device_id设备 ID
order_id订货号
serial_number序列号
hardware_revision硬件版本
software_revision软件版本
product_name产品名
im_supported已启用的 I&M 记录集
im14_supportedI&M1–4 是否启用(0 / 1)
im_note标识说明
project_order_number工程订货号
project_hardware_release工程硬件版本
project_software_release工程软件版本
im1_tag_functionI&M1 功能标签
im1_tag_locationI&M1 安装位置
im2_dateI&M2 日期
im3_descriptorI&M3 描述
im4_signature_hexI&M4 签名(十六进制)
pns_service_im_info_t im;
if (PnSServiceGetIm(session, &im) == PNS_OK)
printf("%s vendor=0x%04X device=0x%04X\n",
im.station_name, im.vendor_id, im.device_id);

过程数据读写

结构体按声明顺序紧排。字 / 双字为大端。详见 过程数据

金路径是 0 拷贝:映射一次,源头变字段自己变。多字节字段是网络大端(线上字节序),要宿主数值走「自动转换」的类型化访问器。

#pragma pack(push, 1)
typedef struct {
uint8_t a;
int16_t b;
uint8_t flag;
} from_plc_t;
#pragma pack(pop)

volatile uint8_t *q = NULL;
const uint8_t *i = NULL;
size_t ni = 0, nq = 0;
if (PnSProcessDataInputsMappingRO(session, &i, &ni) != PNS_OK ||
PnSProcessDataOutputsMapping(session, &q, &nq) != PNS_OK ||
i == NULL || q == NULL) /* 失败时 *p = NULL */
{
/* 过程映像不可用 */
}
const from_plc_t *inp = (const from_plc_t *)i; /* I 只读视图 */
from_plc_t *outp = (from_plc_t *)q;
uint8_t present = inp->a; /* 总线刷新后自己变 */
outp->a = 1; /* 直接落 Q 过程映像 */

/* 快照:拷出来不会自己变 */
from_plc_t rx;
PnSProcessDataReadStruct(session, &rx, (uint16_t)sizeof(rx));

PnSProcessDataOutU8(session, 0, 0x11);
uint8_t v = 0;
PnSProcessDataInU8(session, 0, &v);

诊断与报警

通过 PnSServiceGetDiag / PnSServiceGetAlarms 读诊断(与 C# device.Diagnostics 同一组能力)。详见 诊断。事件见 事件

pns_service_diag_t snap;
if (PnSServiceGetDiag(session, &snap) == PNS_OK && !snap.ok)
printf("%s\n", snap.message);

pns_service_alarm_item_t items[PNS_SERVICE_MAX_ALARMS];
size_t n = 0;
if (PnSServiceGetAlarms(session, items, PNS_SERVICE_MAX_ALARMS, &n) == PNS_OK)
{
size_t i;
for (i = 0; i < n; i++)
printf("%s\n", items[i].message);
}