夜雨聆风学习资料网

ARTICLE · 1092954

第26篇_源码加更 08|真机测试、编译入口和 PLC 主程序

第26篇_源码加更 08|真机测试、编译入口和 PLC 主程序

适合谁收藏

  • 准备复用本组源码并审查对象边界的工程师。
  • 需要把公开代码装配进目标 CodeSys 工程的人。
  • 准备重新完成编译、离线测试和真机验证的读者。

开源范围 本篇完整公开 4 个 ST 文件。代码直接读取已验证工程,保留声明、实现、注释和缩进;没有伪代码,没有跨文件拼接,也没有省略号。

先给结论

最后一组源码把公共内核、Server、Client、离线测试和真机测试装配到周期任务中,形成可复现工程入口。 本篇的通过标准不是“代码已经贴出”,而是每个文件的职责、调用位置、状态边界和验证入口都能对应起来,并且完整代码可逐字回查源文件。

读图重点

先找到 GVL_HttpRealTest 在本组中的位置,再沿图确认其余对象分别承担数据、状态、执行或诊断职责。图只给阅读顺序,最终判断必须回到下面的完整 ST 代码。

先看文件职责

序号
文件
职责
行数
1
GVL_HttpRealTest.st
真机测试参数与观察量
87
2
PRG_HttpRealTest.st
真机测试执行程序
16
3
PRG_HttpCompileTouch.st
编译触达入口
16
4
PLC_PRG.st
PLC 周期装配入口
154

阅读顺序不是按文件名机械展开。先看数据和状态,再看公开方法,最后顺着错误出口和调用对象检查边界。源码篇的目标是让读者能对照工程复现,不是用大段代码制造篇幅。

从协议约束到代码职责

协议约束

最后一组源码把公共内核、Server、Client、离线测试和真机测试装配到周期任务中,形成可复现工程入口。 协议层只定义消息与状态成立的条件,工程层还必须把条件分配给确定对象,避免 Parser、Builder、Server、Client 和测试入口互相越权。

对象分工

  • 第 1 个对象 GVL_HttpRealTest.st
    :承担“真机测试参数与观察量”。阅读时先确认输入与公开输出,再追状态、长度和错误出口,最后核对它被谁周期调用或被哪个对象消费。
  • 第 2 个对象 PRG_HttpRealTest.st
    :承担“真机测试执行程序”。阅读时先确认输入与公开输出,再追状态、长度和错误出口,最后核对它被谁周期调用或被哪个对象消费。
  • 第 3 个对象 PRG_HttpCompileTouch.st
    :承担“编译触达入口”。阅读时先确认输入与公开输出,再追状态、长度和错误出口,最后核对它被谁周期调用或被哪个对象消费。
  • 第 4 个对象 PLC_PRG.st
    :承担“PLC 周期装配入口”。阅读时先确认输入与公开输出,再追状态、长度和错误出口,最后核对它被谁周期调用或被哪个对象消费。

装配与验证

这组文件必须作为一个职责单元阅读和编译。先用确定输入验证“真机参数集中管理”,再制造非法或容量边界验证“编译触达防止对象未被工程引用”,最后在真实通信或上层调用中确认“PLC_PRG 是运行装配点而不是业务大杂烩”。如果单文件测试通过但装配后失败,应优先检查结构体、常量、状态枚举和周期调用关系,而不是立即重写核心算法。源码完整公开只证明读者拿到了同一事实源,目标运行时是否通过仍需重新编译和真机取证。

本篇从 GVL_HttpRealTest.st 开始审查:先确认“真机参数集中管理”对应的类型、常量或公开输入,再沿 CASE 或方法调用追踪成功路径,随后逐个检查容量、超时和协议错误出口,最后在 PLC_PRG.st 对应的结果或装配位置确认错误能被观测、清理并再次执行。这个顺序专门用来区分“算法正确但没有周期调用”“状态能完成但错误被覆盖”和“PLC_PRG 是运行装配点而不是业务大杂烩尚未形成验证证据”三类问题。只有本篇源码、装配和验证使用同一组对象与同一组边界,完整开源才具有可复现意义。

本篇完整开源代码

下面按职责顺序给出本篇全部 ST 文件。每个代码块保留完整声明与实现;阅读时把状态、长度、错误出口和调用对象与上面的职责表逐项对照。

完整源码 1:GVL_HttpRealTest.st

职责:真机测试参数与观察量

/// 功能    : HTTP 真机联调控制和结果变量。/// 库依赖  : CAA Net Base Services{attribute 'qualified_only'}VAR_GLOBAL    bResetResults               : BOOL := FALSE;                                            // 一次性复位真机联调结果和命令位。    udiNowMs                    : UDINT := 0;                                               // 示例任务毫秒时钟,按扫描周期累加。    bServerEnable               : BOOL := TRUE;                                             // Server 使能,下载后默认监听,便于通信猫直接访问 PLC。    bServerCloseConnection      : BOOL := TRUE;                                             // Server 响应后主动关闭连接,匹配通信猫短连接调试习惯。    sServerBindIP               : STRING := '0.0.0.0';                                      // Server 绑定 IP,0.0.0.0 表示任意网卡。    uiServerPort                : UINT := GVL_Http.cnDefaultServerPort;                     // Server 监听端口,默认 18088,匹配通信猫访问 PLC 的 URL。    uiServerResponseStatusCode  : UINT := 200;                                              // Server 自定义响应状态码,内置路由默认 200。    sServerResponseBody         : STRING(GVL_Http.cnMaxBodySize) := 'hello from PLC Server';// Server 自定义响应 body,非空时未知路径也返回 200。    sServerResponseContentType  : STRING(96) := GVL_Http.cnDefaultContentType;              // Server 自定义响应 Content-Type。    sServerAdditionalHeader     : STRING(GVL_Http.cnMaxHeaderSize) := '';                   // Server 自定义响应 Header 行。    bServerListening            : BOOL := FALSE;                                            // Server 已获得监听句柄。    bServerRunning              : BOOL := FALSE;                                            // Server 正在运行。    bServerBusy                 : BOOL := FALSE;                                            // Server 正在初始化或等待监听。    bServerError                : BOOL := FALSE;                                            // Server 错误锁存。    diServerErrorID             : DINT := 0;                                                // Server 错误诊断码。    sServerDiagMsg              : STRING(255) := '';                                        // Server 诊断文本。    eServerState                : E_HttpServerState := E_HttpServerState.iDisabled;         // Server 状态机。    eServerLastError            : E_HttpError := E_HttpError.iNoError;                      // Server 最近 HTTP 错误。    eServerLastNbsError         : NBS.ERROR;                                                // Server 最近 NBS 错误。    uiServerActiveConnections   : UINT := 0;                                                // Server 当前活跃连接数。    uiServerLastRequestSlot     : UINT := 0;                                                // Server 最近请求槽位。    uiServerLastErrorSlot       : UINT := 0;                                                // Server 最近错误槽位。    sServerLastTarget           : STRING(GVL_Http.cnMaxTargetLen) := '';                    // Server 最近请求路径。    sServerLastBody             : STRING(GVL_Http.cnMaxBodySize) := '';                     // Server 最近请求 body。    sServerRxMessage            : STRING(GVL_Http.cnMaxMessageSize) := '';                  // Server 最近一次接收报文。    sServerTxMessage            : STRING(GVL_Http.cnMaxMessageSize) := '';                  // Server 最近一次发送报文。    udiServerAcceptedCount      : UDINT := 0;                                               // Server 累计接入连接数。    udiServerRequestCount       : UDINT := 0;                                               // Server 累计请求数。    udiServerResponseCount      : UDINT := 0;                                               // Server 累计响应数。    udiServerProtocolErrorCount : UDINT := 0;                                               // Server 累计协议错误数。    hServerListenHandle         : NBS.CAA.HANDLE;                                           // Server 监听句柄快照。    bServerPassLatched          : BOOL := FALSE;                                            // Server 外部 client 联调通过锁存。    bClientEnable               : BOOL := TRUE;                                             // Client 使能,下载后可直接向通信猫发起 HTTP 请求。    bClientSend                 : BOOL := TRUE;                                             // Client 下载后默认发送一次,PLC_PRG 读取后自复位。    bClientAbort                : BOOL := FALSE;                                            // Client 中止当前连接命令。    bClientCloseConnection      : BOOL := TRUE;                                             // Client 每次响应后主动关闭连接,优先保证通信猫短连接调试稳定。    udiClientTimeoutUs          : UDINT := 10000000;                                        // Client 请求超时,单位 [us],通信猫联调默认 10 s。    sClientURL                  : STRING(1024) := '';                                       // Client URL 留空时使用下方 IP/Host/Path 分离引脚。    sClientServerIP             : STRING := '192.168.20.2';                                 // Client 远端 HTTP Server IP。    uiClientPort                : UINT := 6971;                                             // Client 远端 HTTP Server 端口,匹配通信猫 HTTP 服务端口。    sClientHost                 : STRING(GVL_Http.cnMaxHostLen) := '192.168.20.2:6971';     // Client Host 字段,匹配通信猫监听端口。    sClientPath                 : STRING(GVL_Http.cnMaxTargetLen) := '/api/tongxinmao';     // Client 请求路径,匹配通信猫 URL。    eClientMethod               : E_HttpMethod := E_HttpMethod.iPost;                       // Client 请求方法,默认 POST 便于发送正文。    sClientBody                 : STRING(GVL_Http.cnMaxBodySize) := 'hello from PLC';       // Client 请求 body,通信猫接收区可直接看到。    sClientContentType          : STRING(96) := 'text/plain';                               // Client Content-Type,匹配通信猫普通文本联调。    sClientAdditionalHeader     : STRING(GVL_Http.cnMaxHeaderSize) := '';                   // Client 自定义 Header 行。    bClientTcpConnected         : BOOL := FALSE;                                            // Client TCP 连接快照。    bClientBusy                 : BOOL := FALSE;                                            // Client 正在执行事务。    bClientDone                 : BOOL := FALSE;                                            // Client 本次事务完成。    bClientError                : BOOL := FALSE;                                            // Client 错误锁存。    diClientErrorID             : DINT := 0;                                                // Client 错误诊断码。    sClientDiagMsg              : STRING(255) := '';                                        // Client 诊断文本。    eClientState                : E_HttpClientState := E_HttpClientState.iDisabled;         // Client 状态机。    eClientLastError            : E_HttpError := E_HttpError.iNoError;                      // Client 最近 HTTP 错误。    eClientLastNbsError         : NBS.ERROR;                                                // Client 最近 NBS 错误。    uiClientStatusCode          : UINT := 0;                                                // Client 最近 HTTP 响应状态码。    sClientReason               : STRING(64) := '';                                         // Client 最近 HTTP 响应原因短语。    sClientResponseBody         : STRING(GVL_Http.cnMaxBodySize) := '';                     // Client 最近 HTTP 响应 body。    sClientResponseHeader       : STRING(GVL_Http.cnMaxHeaderSize) := '';                   // Client 最近 HTTP 响应 Header。    sClientTxMessage            : STRING(GVL_Http.cnMaxMessageSize) := '';                  // Client 最近一次发送报文。    sClientRxMessage            : STRING(GVL_Http.cnMaxMessageSize) := '';                  // Client 最近一次接收报文。    udiClientRequestCount       : UDINT := 0;                                               // Client 累计请求数。    udiClientResponseCount      : UDINT := 0;                                               // Client 累计响应数。    udiClientConnectErrorCount  : UDINT := 0;                                               // Client 累计连接错误数。    udiClientProtocolErrorCount : UDINT := 0;                                               // Client 累计协议错误数。    bClientPassLatched          : BOOL := FALSE;                                            // Client 外部 server 联调通过锁存。    bOverallPassLatched         : BOOL := FALSE;                                            // Server 与 Client 双向联调均通过锁存。    bClientMatrixAutoEnable     : BOOL := FALSE;                                            // 真机矩阵自动运行开关,发布默认关闭,避免下载后自动访问外部网络。    bClientMatrixRun            : BOOL := FALSE;                                            // 真机矩阵运行命令,由自动开关或在线命令置位。    bClientMatrixDone           : BOOL := FALSE;                                            // 真机矩阵完成标志。    bClientMatrixPassed         : BOOL := FALSE;                                            // 真机矩阵全部通过标志。    bClientMatrixError          : BOOL := FALSE;                                            // 真机矩阵存在失败用例标志。    uiClientMatrixTotal         : UINT := 15;                                               // 真机矩阵用例总数。    uiClientMatrixPassed        : UINT := 0;                                                // 真机矩阵通过用例数。    uiClientMatrixFailed        : UINT := 0;                                                // 真机矩阵失败用例数。    uiClientMatrixCase          : UINT := 0;                                                // 真机矩阵当前用例序号。    uiClientMatrixStep          : UINT := 0;                                                // 真机矩阵内部步骤快照。    uiClientMatrixLastStatus    : UINT := 0;                                                // 最近一次 Client 响应状态码。    eClientMatrixLastError      : E_HttpError := E_HttpError.iNoError;                      // 最近一次 Client 协议栈错误码。    sClientMatrixCaseID         : STRING(48) := '';                                         // 当前真机矩阵用例 ID。    sClientMatrixFailedCase     : STRING(48) := '';                                         // 首个失败用例 ID。    sClientMatrixDiagMsg        : STRING(255) := '';                                        // 真机矩阵诊断文本。END_VAR

完整源码 2:PRG_HttpRealTest.st

职责:真机测试执行程序

/// 功能    : HTTP 真机联调旧入口兼容占位。/// 库依赖  : CAA Net Base ServicesPROGRAM PRG_HttpRealTestVAREND_VAR// === IMPLEMENTATION ===/// =======================================================================/// 名称      : PRG_HttpRealTest/// 功能      : 保留旧工程树对象名称,真实 Server/Client 联调入口已统一到 PLC_PRG。/// 库依赖    : CAA Net Base Services/// =======================================================================/// 使用说明  : 1. 本程序不再实例化 HTTP 功能块,不再处理发送、复位或中止命令。///           : 2. 在线联调请直接打开 PLC_PRG,操作 GVL_HttpRealTest 中的全局变量。/// =======================================================================// 兼容原因:当前 SmartControl CLI 删除 IEC 对象能力受限,保留空 PRG 可避免旧入口继续干扰在线联调。

完整源码 3:PRG_HttpCompileTouch.st

职责:编译触达入口

/// 功能    : HTTP 编译触达旧入口兼容占位。/// 库依赖  : CAA Net Base ServicesPROGRAM PRG_HttpCompileTouchVAREND_VAR// === IMPLEMENTATION ===/// =======================================================================/// 名称      : PRG_HttpCompileTouch/// 功能      : 保留旧工程树对象名称,当前 HTTP 对象由 PLC_PRG 中的完整功能块调用覆盖。/// 库依赖    : CAA Net Base Services/// =======================================================================/// 使用说明  : 1. 本程序不再实例化 Client、Server 或连接槽位功能块。///           : 2. 编译与联调以 PLC_PRG 为唯一用户入口。/// =======================================================================// 兼容原因:当前 SmartControl CLI 删除 IEC 对象能力受限,空 PRG 仅用于保持工程树兼容。

完整源码 4:PLC_PRG.st

职责:PLC 周期装配入口

/// 功能    : HTTP 示例工程任务入口。/// 库依赖 : CAA Net Base ServicesPROGRAM PLC_PRGVAR    fbHttpClient        : FB_HttpClient;                                                       // HTTP Client 主实例。    fbHttpServer        : FB_HttpServer;                                                       // HTTP Server 主实例。    stClientMetrics     : ST_HttpClientMetrics;                                                // Client 指标输出。    stServerMetrics     : ST_HttpServerMetrics;                                                // Server 指标输出。    stClientResponse    : ST_HttpResponse;                                                     // Client 响应输出。    aServerSnapshots    : ARRAY[1..GVL_Http.cnMaxClientSlots] OF ST_HttpConnectionSnapshot;    // Server 连接快照。END_VAR// === IMPLEMENTATION ===/// =======================================================================/// 名称      : PLC_PRG/// 功能      : HTTP 示例工程主任务,直接完整调用 Client 和 Server 功能块。/// 库依赖    : CAA Net Base Services/// =======================================================================/// 使用说明  : 1. Client/Server 所有真实网络命令默认关闭,由 GVL_HttpRealTest 在线变量触发。///           : 2. 本主程序完整列出功能块引脚,便于 CODESYS/SmartControl 用户按引脚理解用法。/// =======================================================================// 工程说明:本段集中处理状态、边界或诊断,避免跨周期残留。// 约束:PLC_PRG 作为示例主入口直接调用 HTTP 功能块;用户联调不再依赖辅助 PRG。GVL_HttpRealTest.udiNowMs := GVL_HttpRealTest.udiNowMs + 10;IF GVL_HttpRealTest.bResetResults THEN    fbHttpServer.M_Reset();    fbHttpClient.M_Reset();    GVL_HttpRealTest.bClientSend := FALSE;    GVL_HttpRealTest.bClientAbort := FALSE;    GVL_HttpRealTest.bServerPassLatched := FALSE;    GVL_HttpRealTest.bClientPassLatched := FALSE;    GVL_HttpRealTest.bOverallPassLatched := FALSE;END_IFfbHttpServer(    xEnable              := GVL_HttpRealTest.bServerEnable,    xReset               := GVL_HttpRealTest.bResetResults,    xCloseConnection     := GVL_HttpRealTest.bServerCloseConnection,    bEnable              := GVL_HttpRealTest.bServerEnable,    sBindIP              := GVL_HttpRealTest.sServerBindIP,    uiPort               := GVL_HttpRealTest.uiServerPort,    uiResponseStatusCode := GVL_HttpRealTest.uiServerResponseStatusCode,    sResponseBody        := GVL_HttpRealTest.sServerResponseBody,    sResponseContentType := GVL_HttpRealTest.sServerResponseContentType,    sAdditionalHeader    := GVL_HttpRealTest.sServerAdditionalHeader,    udiNowMs             := GVL_HttpRealTest.udiNowMs,    xListening           => GVL_HttpRealTest.bServerListening,    xRunning             => GVL_HttpRealTest.bServerRunning,    xBusy                => GVL_HttpRealTest.bServerBusy,    xError               => GVL_HttpRealTest.bServerError,    bListening           => GVL_HttpRealTest.bServerListening,    bRunning             => GVL_HttpRealTest.bServerRunning,    bBusy                => GVL_HttpRealTest.bServerBusy,    bError               => GVL_HttpRealTest.bServerError,    diErrorID            => GVL_HttpRealTest.diServerErrorID,    sDiagMsg             => GVL_HttpRealTest.sServerDiagMsg,    eLastNbsError        => GVL_HttpRealTest.eServerLastNbsError,    eState               => GVL_HttpRealTest.eServerState,    eLastError           => GVL_HttpRealTest.eServerLastError,    stMetrics            => stServerMetrics,    uiActiveConnections  => GVL_HttpRealTest.uiServerActiveConnections,    uiLastErrorSlot      => GVL_HttpRealTest.uiServerLastErrorSlot,    uiLastRequestSlot    => GVL_HttpRealTest.uiServerLastRequestSlot,    sRequestTarget       => GVL_HttpRealTest.sServerLastTarget,    sRequestBody         => GVL_HttpRealTest.sServerLastBody,    sRxMessage           => GVL_HttpRealTest.sServerRxMessage,    sTxMessage           => GVL_HttpRealTest.sServerTxMessage,    sLastTarget          => GVL_HttpRealTest.sServerLastTarget,    sLastBody            => GVL_HttpRealTest.sServerLastBody,    hListenHandle        => GVL_HttpRealTest.hServerListenHandle,    aConnectionSnapshots => aServerSnapshots    );fbHttpClient(    xEnable           := GVL_HttpRealTest.bClientEnable,    xExecute          := GVL_HttpRealTest.bClientSend,    xReset            := GVL_HttpRealTest.bResetResults,    xAbort            := GVL_HttpRealTest.bClientAbort,    xCloseConnection  := GVL_HttpRealTest.bClientCloseConnection,    bEnable           := GVL_HttpRealTest.bClientEnable,    bSend             := GVL_HttpRealTest.bClientSend,    udiTimeOut        := GVL_HttpRealTest.udiClientTimeoutUs,    sURL              := GVL_HttpRealTest.sClientURL,    sServerIP         := GVL_HttpRealTest.sClientServerIP,    uiPort            := GVL_HttpRealTest.uiClientPort,    sHost             := GVL_HttpRealTest.sClientHost,    sPath             := GVL_HttpRealTest.sClientPath,    eRequestType      := GVL_HttpRealTest.eClientMethod,    eMethod           := GVL_HttpRealTest.eClientMethod,    sBody             := GVL_HttpRealTest.sClientBody,    sContentType      := GVL_HttpRealTest.sClientContentType,    sAdditionalHeader := GVL_HttpRealTest.sClientAdditionalHeader,    udiNowMs          := GVL_HttpRealTest.udiNowMs,    xActive           => GVL_HttpRealTest.bClientTcpConnected,    xConnected        => GVL_HttpRealTest.bClientTcpConnected,    xBusy             => GVL_HttpRealTest.bClientBusy,    xDone             => GVL_HttpRealTest.bClientDone,    xError            => GVL_HttpRealTest.bClientError,    bTcpConnected     => GVL_HttpRealTest.bClientTcpConnected,    bBusy             => GVL_HttpRealTest.bClientBusy,    bDone             => GVL_HttpRealTest.bClientDone,    bError            => GVL_HttpRealTest.bClientError,    diErrorID         => GVL_HttpRealTest.diClientErrorID,    sDiagMsg          => GVL_HttpRealTest.sClientDiagMsg,    eLastNbsError     => GVL_HttpRealTest.eClientLastNbsError,    eState            => GVL_HttpRealTest.eClientState,    eLastError        => GVL_HttpRealTest.eClientLastError,    uiStatusCode      => GVL_HttpRealTest.uiClientStatusCode,    sTxMessage        => GVL_HttpRealTest.sClientTxMessage,    sRxMessage        => GVL_HttpRealTest.sClientRxMessage,    sResponseBody     => GVL_HttpRealTest.sClientResponseBody,    sResponseHeader   => GVL_HttpRealTest.sClientResponseHeader,    stMetrics         => stClientMetrics,    stResponse        => stClientResponse    );IF GVL_HttpRealTest.bClientSend THEN    GVL_HttpRealTest.bClientSend := FALSE;END_IFIF GVL_HttpRealTest.bClientAbort THEN    GVL_HttpRealTest.bClientAbort := FALSE;END_IFIF GVL_HttpRealTest.bResetResults THEN    GVL_HttpRealTest.bResetResults := FALSE;END_IFGVL_HttpRealTest.udiServerAcceptedCount := stServerMetrics.udiAcceptedConnections;GVL_HttpRealTest.udiServerRequestCount := stServerMetrics.udiRequestCount;GVL_HttpRealTest.udiServerResponseCount := stServerMetrics.udiResponseCount;GVL_HttpRealTest.udiServerProtocolErrorCount := stServerMetrics.udiProtocolErrorCount;GVL_HttpRealTest.udiClientRequestCount := stClientMetrics.udiRequestCount;GVL_HttpRealTest.udiClientResponseCount := stClientMetrics.udiResponseCount;GVL_HttpRealTest.udiClientConnectErrorCount := stClientMetrics.udiConnectErrorCount;GVL_HttpRealTest.udiClientProtocolErrorCount := stClientMetrics.udiProtocolErrorCount;GVL_HttpRealTest.sClientReason := stClientResponse.sReason;IF (GVL_HttpRealTest.udiServerRequestCount > 0)    AND (GVL_HttpRealTest.udiServerResponseCount > 0)    AND NOT GVL_HttpRealTest.bServerError THEN    GVL_HttpRealTest.bServerPassLatched := TRUE;END_IFIF GVL_HttpRealTest.bClientDone    AND NOT GVL_HttpRealTest.bClientError    AND (GVL_HttpRealTest.uiClientStatusCode >= 200)    AND (GVL_HttpRealTest.uiClientStatusCode < 300) THEN    GVL_HttpRealTest.bClientPassLatched := TRUE;END_IFGVL_HttpRealTest.bOverallPassLatched := GVL_HttpRealTest.bServerPassLatched    AND GVL_HttpRealTest.bClientPassLatched;

本篇阅读抓手

  • 真机参数集中管理。
  • 编译触达防止对象未被工程引用。
  • PLC_PRG 是运行装配点而不是业务大杂烩。

如何验证这组源码

  1. 先针对 GVL_HttpRealTest.st 的公开输入和错误出口建立确定性用例。
  2. 再把“真机参数集中管理”转成至少一个正常场景和一个失败场景。
  3. 本篇 4 个文件必须一起编译,避免只验证单个函数而漏掉数据结构或调用边界。
  4. 真机复核时重点观察“PLC_PRG 是运行装配点而不是业务大杂烩”,并保留对应状态、计数和原始报文。

这一篇你最该记住

  • 真机参数集中管理。
  • 编译触达防止对象未被工程引用。
  • PLC_PRG 是运行装配点而不是业务大杂烩。

系列导航

  • 系列:CodeSys HTTP 系列教程,第 26/28 篇。
  • 当前源码加更:第 8/8 篇。
  • 本篇完整源码文件数:4。
  • 上一篇:第25篇
  • 下一篇:第27篇

相关学习资料