• 正文
  • 相关推荐
申请入驻 产业图谱

大众VASS标准:FB_Typ_VAR(FB529)车型匹配功能块深度解读

10/07 11:58
1034
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

前几天我们对RFID读取功能块和校验功能块进行了解读

大众VASS标准:FB_Sick_RFU(FB520_RFID数据读取)功能块深度解读

大众VASS标准:FB_Pruefziffer(FB170)校验数据功能块深度解读

今天我们对FB_Typ_VAR(FB529)车辆代码匹配功能块进行详细解读

功能块简介

FB_Typ_VAR(FB529)核心作用是实现对车辆代码(RBS)接收与有效性校验、车型类型匹配评估,并提供可视化交互与故障监控能力。

功能块:

功能块大纲:

1初始化与参数计算

- 数据块缓存:通过`BLKMOV`将`DB_RBS`和`DB_STyp`复制到临时缓存(`tempDB_RBS`/`tempDB_STyp`)

- 参数计算:`iRBSAnz`(RBS位数)、`iRBSLen`(RBS长度,含校验位)、`iTypAnz`(工作站类型条目数)

2 RBS接收与处理

- 指针配置:`anyRBS`指向RBS数据(设置语法ID、数据类型、长度)

- 手动接收:从可视化界面读取RBS字符(`strVisuWertRBS`)或软键输入

- 自动接收:通过`BLKMOV`从RBS数据块自动读取

3 有效性校验

- RBS校验:逐位匹配`tempDB_RBS`中的有效字符,设置`arrRBS_IO`(位置正常)

- 校验位计算:基于Code39算法,计算`chrPZ`并与输入比对(`xCODE39_IO`)

- 整体有效性:`xRBS_PZ_IO`(RBS+校验位正常)、`xRBS_PZ_NIO`(异常)

4 工作站类型评估

- 匹配逻辑:对比RBS与`tempDB_STyp`中的类型条目,支持占位符`X`/`~`(由`Cfg.X2`控制)

- 状态标志:`xSTyp_IO`(类型正常)、`xSTyp_NIO`(类型异常)

5 接收确认与输出

- 接收触发:自动模式或手动软键触发,设置`xUebern`(RBS已接收)

- 输出映射:`RBS_IO`/`STypIO`等状态输出,`RBS_S1`至`RBS_S8`编码输出

6 可视化与消息系统

- 可视化控制:颜色配置(`bFarbKombi`)、文本更新(多语言支持)

- 故障消息:`MSYS`记录故障源,通过`MeldSend`发送至消息缓冲区

- 故障汇总:`xStoe`(汇总故障)、`VkStoe_Out`(连锁故障)

变量声明:

1. 输入变量(VAR_INPUT)

完整代码解读:

### 西门子SCL功能块FB_Typ_VAR(FB529)详细解读#### 一、版权与版本日志```plaintext*******************************************************************************************                                                                                      ****  Copyright  2013             SIEMENS AG I IA/DT, D-90475 Nuernberg                   ****  All Rights Reserved         VOLKSWAGEN AG, 38436 Wolfsburg                          ****                              AUDI AG, D-85045 Ingolstadt                             ****                                                                                      **********************************************************************************************                                                                                      **** Aenderungsjournal  :                                                                 **********************************************************************************************  Datum       Version     Autor       Beschreibung                                    **------------------------------------------------------------------------------------------    07.09.15    3.1.03      Schulz      在有效工作站类型的声明中,'X'可作为占位符;若cfg.x2=true,'~'可作为占位符    22.01.15    3.1.02      Schulz      移除了德语变音符号    06.12.13    3.1.02      Maletz      调整了类型错误消息    03.12.13    3.1.01      Maletz      校验位可关闭(Cfg.X1)    21.10.13    3.1.00      Maletz      扩展校验位功能;扩展可变RBS长度    14.10.13    3.0.01      Maletz      调整手动输入    20.08.13    3.0.00      Maletz      重新创建*****************************************************************************************```**解读**:  - 版权归属西门子、大众、奥迪公司,功能块用于工业控制场景(推测与汽车生产中的毛坯代码/工作站类型评估相关)。  - 版本迭代记录了功能扩展(如校验位、占位符)、bug修复(如变音符号移除)等,最新版本为3.1.03。  #### 二、功能块基本信息```sclFUNCTION_BLOCK FB_Typ_VAR    //FB529TITLE   = 'Version 3.1.03'VERSION : '3.1'AUTHOR  : VASS_V05NAME    : TYPVARFAMILY  : TYPVAR```**解读**:  - 定义功能块`FB_Typ_VAR`,编号`FB529`,版本3.1.03,作者VASS_V05,名称TYPVAR,属于TYPVAR家族(功能块组)。  #### 三、变量声明##### 1. 输入变量(VAR_INPUT)```sclVAR_INPUT    Init                    : BOOL;         //初始化(重新读取数据块)                    RBS                     : POINTER;      //指向UII_RBS起始地址的指针        pRBS AT RBS         : STRUCT             DBNR            : WORD;         //字节4+5:DB编号             BZ              : DWORD;        //字节6至10:区域指针         END_STRUCT;    DB_RBS                  : ANY;          //毛坯代码数据块(DB_RBS)        pDB_RBS AT DB_RBS   : STRUCT             BYTE0           : BYTE;         //字节0             TYP             : BYTE;         //字节1:数据/参数类型             ANZ             : WORD;         //字节2+3:变量长度             DBNR            : WORD;         //字节4+5:DB编号             BZ              : DWORD;        //字节6至10:区域指针         END_STRUCT;     DB_STyp                 : ANY;          //工作站类型数据块        pDB_STyp AT DB_STyp : STRUCT             BYTE0           : BYTE;         //字节0             TYP             : BYTE;         //字节1:数据/参数类型             ANZ             : WORD;         //字节2+3:变量长度             DBNR            : WORD;         //字节4+5:DB编号             BZ              : DWORD;        //字节6至10:区域指针         END_STRUCT;     Sprache                 : INT;          //语言(1:德语;2:其他语言;3:中文)    Auto                    : BOOL;         //自动类型评估使能     Hand                    : BOOL;         //手动类型评估使能    FM_Reset                : BOOL;         //清除类型接收标志    _Cfg                    : WORD;         //配置字(X0:评估DB_RBS预设位置2-x;X1:无校验位;X2:占位符'~'替代'X')        Cfg AT _Cfg         : STRUCT        //WORD拆分为BOOL            X8              : BOOL;            X9              : BOOL;            X10             : BOOL;            X11             : BOOL;            X12             : BOOL;            X13             : BOOL;            X14             : BOOL;            X15             : BOOL;            X0              : BOOL;         //评估DB_RBS预设位置2-x            X1              : BOOL;         //无校验位            X2              : BOOL;         //工作站类型评估:用'~'作为占位符(替代'X')            X3              : BOOL;            X4              : BOOL;            X5              : BOOL;            X6              : BOOL;            X7              : BOOL;        END_STRUCT;    VkStoe_In               : BOOL;         //连锁故障输入 END_VAR```**解读**:  - `Init`:触发数据块重新读取(初始化)。  - `RBS`:指针类型,通过`pRBS`结构体解析为`DBNR`(数据块编号)和`BZ`(区域指针,指向数据存储位置),用于定位毛坯代码(RBS)数据。  - `DB_RBS`/`DB_STyp`:`ANY`类型(任意数据类型指针),分别指向毛坯代码和工作站类型的数据块,通过`pDB_RBS`/`pDB_STyp`解析内部结构(含长度、DB编号等元数据)。  - `Sprache`:设置语言(支持中文)。  - `Auto`/`Hand`:自动/手动模式使能,控制类型评估方式。  - `FM_Reset`:清除“类型已接收”标志(`FM`)。  - `_Cfg`:配置字,通过`Cfg`结构体拆分为16个BOOL位,分别控制功能(如`X1`关闭校验位,`X2`切换占位符)。  - `VkStoe_In`:外部连锁故障输入,用于故障传递。  ##### 2. 输出变量(VAR_OUTPUT)```sclVAR_OUTPUT    FM                      : BOOL;         //毛坯代码已接收     RBS_IO                  : BOOL;         //毛坯代码正常     RBS_NIO                 : BOOL;         //毛坯代码异常    STypIO                  : BOOL;         //工作站类型正常     STypNIO                 : BOOL;         //工作站类型异常    Data                    : WORD;         //工作站类型数据    RBS_S1                  : WORD;         //毛坯代码位1(位编码)    RBS_S2                  : WORD;         //毛坯代码位2(位编码)    RBS_S3                  : WORD;         //毛坯代码位3(位编码)    RBS_S4                  : WORD;         //毛坯代码位4(位编码)    RBS_S5                  : WORD;         //毛坯代码位5(位编码)    RBS_S6                  : WORD;         //毛坯代码位6(位编码)    RBS_S7                  : WORD;         //毛坯代码位7(位编码)    RBS_S8                  : WORD;         //毛坯代码位8(位编码)    Stoe                    : BOOL;         //汇总故障     VkStoe_Out              : BOOL;         //连锁故障输出 END_VAR```**解读**:  - `FM`:毛坯代码成功接收标志。  - `RBS_IO`/`RBS_NIO`:毛坯代码是否有效(正常/异常)。  - `STypIO`/`STypNIO`:工作站类型是否有效(正常/异常)。  - `Data`:工作站类型对应的输出数据。  - `RBS_S1`至`RBS_S8`:毛坯代码各位置的位编码(用于外部传递具体位状态)。  - `Stoe`:汇总故障标志(所有故障的OR结果)。  - `VkStoe_Out`:连锁故障输出(输入故障与内部故障的OR结果)。  ##### 3. 输入输出变量(VAR_IN_OUT)```sclVAR_IN_OUT    ST_Meld                 : Meldungspuffer;   //消息缓冲区(消息结构体)END_VAR```**解读**:  - `ST_Meld`:消息缓冲区,用于传递故障/状态消息(与消息系统交互)。  ##### 4. 临时变量(VAR_Temp)```sclVAR_Temp    TempPointerMsys         : ANY;          //消息系统辅助指针    TempPointerFlanken      : ANY;          //边沿检测辅助指针    TempPointerMeldpuffer   : ANY;          //消息缓冲区辅助指针    erg_SFC20               : INT;          //SFC20(块移动指令)返回值    pMeldFeld AT TempPointerMsys: STRUCT         BYTE0               : BYTE;         //字节0         TYP                 : BYTE;         //字节1:数据/参数类型         ANZ                 : WORD;         //字节2+3:变量长度         DBNR                : WORD;         //字节4+5:DB编号         BZ                  : DWORD;        //字节6至10:区域指针     END_STRUCT;                                pMeldAbb AT TempPointerFlanken: STRUCT         BYTE0               : BYTE;         //字节0         TYP                 : BYTE;         //字节1:数据/参数类型         ANZ                 : WORD;         //字节2+3:变量长度         DBNR                : WORD;         //字节4+5:DB编号         BZ                  : DWORD;        //字节6至10:区域指针     END_STRUCT;                               pMeldDBNR AT TempPointerMeldpuffer: STRUCT         BYTE0               : BYTE;         //字节0         TYP                 : BYTE;         //字节1:数据/参数类型         ANZ                 : WORD;         //字节2+3:变量长度         DBNR                : WORD;         //字节4+5:DB编号         BZ                  : DWORD;        //字节6至10:区域指针     END_STRUCT;    bFarbKombi              : BYTE;         //可视化颜色组合    iAdr_RBS                : INT;          //RBS字节地址    anyRBS                  : ANY;          //RBS辅助ANY指针        p_RBS AT anyRBS     : STRUCT             SyntaxId        : BYTE;         //字节0:语法ID(固定为16#10)            DataType        : BYTE;         //字节1:数据类型(如02=BYTE)            DataCount       : WORD;         //字节2+3:重复次数(长度)            DBNR            : WORD;         //字节4+5:DB编号             BZ              : DWORD;        //字节6至10:区域指针         END_STRUCT;     anyDB_RBS1              : ANY;          //DB_RBS辅助指针1        p_DB_RBS1 AT anyDB_RBS1   : STRUCT             SyntaxId        : BYTE;         //语法ID            DataType        : BYTE;         //数据类型            DataCount       : WORD;         //长度            DBNR            : WORD;         //DB编号            BZ              : DWORD;        //区域指针        END_STRUCT;     anyDB_RBS2              : ANY;          //DB_RBS辅助指针2        p_DB_RBS2 AT anyDB_RBS2   : STRUCT             SyntaxId        : BYTE;         //语法ID            DataType        : BYTE;         //数据类型            DataCount       : WORD;         //长度            DBNR            : WORD;         //DB编号            BZ              : DWORD;        //区域指针        END_STRUCT;     anyQRBS_S               : ANY;          //RBS_S源指针        p_QRBS_S AT anyQRBS_S : STRUCT             SyntaxId        : BYTE;         //语法ID            DataType        : BYTE;         //数据类型            DataCount       : WORD;         //长度            DBNR            : WORD;         //DB编号            BZ              : DWORD;        //区域指针        END_STRUCT;     anyZRBS_S               : ANY;          //RBS_S目标指针        p_ZRBS_S AT anyZRBS_S : STRUCT             SyntaxId        : BYTE;         //语法ID            DataType        : BYTE;         //数据类型            DataCount       : WORD;         //长度            DBNR            : WORD;         //DB编号            BZ              : DWORD;        //区域指针        END_STRUCT; END_VAR```**解读**:  - 临时变量用于中间计算,如`erg_SFC20`存储块移动指令的返回值(0表示成功);`anyRBS`系列指针用于动态定位数据块中的数据;`bFarbKombi`控制可视化界面的颜色(如正常为绿色,故障为红色)。  ##### 5. 静态变量(VAR)```sclVAR    _dwVisuWerte1           : DWORD;        //可视化状态双字1         dwVisuWerte1 AT _dwVisuWerte1: STRUCT   //DWORD拆分为BOOL/字节            B3              : BYTE;         //可视化符号03边框(0..3)            B2              : BYTE;         //可视化符号10边框(0..3)            X8              : BOOL;         //预留            X9              : BOOL;         //预留            X10             : BOOL;         //预留            X11             : BOOL;         //预留            X12             : BOOL;         //预留            X13             : BOOL;         //预留            X14             : BOOL;         //预留            X15             : BOOL;         //手动输入RBS接收标志            X0              : BOOL;         //预留            X1              : BOOL;         //预留            X2              : BOOL;         //预留            X3              : BOOL;         //RBS位1故障闪烁            X4              : BOOL;         //RBS位2故障闪烁            X5              : BOOL;         //RBS位3故障闪烁            X6              : BOOL;         //RBS位4故障闪烁            X7              : BOOL;         //RBS位5故障闪烁        END_STRUCT;    _dwVisuWerte2           : DWORD;        //可视化状态双字2         dwVisuWerte2 AT _dwVisuWerte2: STRUCT   //DWORD拆分为字节            B3              : BYTE;         //校验位按钮颜色            B2              : BYTE;         //OK按钮颜色            B1              : BYTE;         //RBS/工作站类型显示(0..3/4..7)            B0              : BYTE;         //手动/自动显示(0..3/4..7)        END_STRUCT;    _strVisuWertRBS         : STRING[10] := '**********'; //可视化RBS字符串        strVisuWertRBS AT _strVisuWertRBS: STRUCT   //字符串结构            bMax            : BYTE;         //最大长度            bAct            : BYTE;         //实际长度            arrText         : ARRAY[1..10] OF CHAR; //RBS字符数组        END_STRUCT;    _strVisuWertPZ          : STRING[2] := '*'; //可视化校验位字符串        strVisuWertPZ AT _strVisuWertPZ: STRUCT     //校验位结构            bMax            : BYTE;         //最大长度            bAct            : BYTE;         //实际长度            arrText         : ARRAY[1..2] OF CHAR; //校验位字符        END_STRUCT;    bVisuTasten             : BYTE;         //可视化软键输入    strVisuText             : STRUCT        //可视化文本结构        S                   : ARRAY[1..8] OF STRUCT            Bez             : STRING[20];  //标题            Z               : ARRAY[1..16] OF STRUCT                Bez         : STRING[30];  //按键文本            END_STRUCT;         END_STRUCT;     END_STRUCT;     iVisuTastenS            : ARRAY[1..8] OF INT;   //可视化软键输入值(****************************************************************************************)(*****************************Anfang Variablendeklaration********************************)(*********************************fuers Meldesystem**************************************)(****************************************************************************************)    MSYS                    : STRUCT        //消息系统标志        xF_1                : BOOL;         //故障标志1(RBS位1异常)        xF_2                : BOOL;         //故障标志2(RBS位2异常)        xF_3                : BOOL;         //故障标志3(RBS位3异常)        xF_4                : BOOL;         //故障标志4(RBS位4异常)        xF_5                : BOOL;         //故障标志5(RBS位5异常)        xF_6                : BOOL;         //故障标志6(RBS位6异常)        xF_7                : BOOL;         //故障标志7(RBS位7异常)        xF_8                : BOOL;         //故障标志8(RBS位8异常)        xF_9                : BOOL;         //故障标志9(工作站类型无效)        xF_10               : BOOL;         //故障标志10(校验位异常)        xF_11               : BOOL;         //故障标志11(手动输入激活)        xF_12               : BOOL;         //预留        xF_13               : BOOL;         //预留        xF_14               : BOOL;         //预留        xF_15               : BOOL;         //预留        xF_16               : BOOL;         //预留        Flanken             : ARRAY[0..1] OF BYTE;    //边沿检测字节    END_STRUCT;    AenderungsID            : STRUCT        //版本ID        SNr                 : WORD;         //序列号        ANr                 : BYTE;         //编号        Detail              : BYTE;         //细节    END_STRUCT;    xIntegritaet            : BOOL;         //完整性标志(消息系统)(****************************************************************************************)(*****************************Ende Variablendeklaration**********************************)(*********************************fuers Meldesystem**************************************)(****************************************************************************************)    xStoe                   : BOOL;         //故障消息激活    xWarn                   : BOOL;         //警告消息激活    xWart                   : BOOL;         //维护消息激活    xInit                   : BOOL;         //初始化完成标志    iStart                  : INT;          //起始地址    iLetzter                : INT;          //结束地址    iLauf                   : INT;          //循环变量1    i                       : INT;          //循环变量2    iRBSAnz                 : INT := 4;     //毛坯代码位数(默认4位)    iTypAnz                 : INT := 1;     //工作站类型DB条目数(默认1)    iRBSLen                 : INT := 5;     //毛坯代码长度(含校验位,默认5)    iSicht_RBS              : INT;          //RBS位2-x的偏移量    iBer_RBS                : INT;          //RBS位2-x的区域长度    arrRBS                  : ARRAY[1..10] OF CHAR; //毛坯代码字符数组    arrTemp                 : ARRAY[1..8] OF BOOL;  //辅助布尔数组    arrRBS_IO               : ARRAY[1..8] OF BOOL;  //RBS各位置正常标志    arrRBS_NIO              : ARRAY[1..8] OF BOOL;  //RBS各位置异常标志    xRBS_IO                 : BOOL;         //RBS整体正常    xRBS_NIO                : BOOL;         //RBS整体异常    xRBS_PZ_IO              : BOOL;         //RBS+校验位正常    xRBS_PZ_NIO             : BOOL;         //RBS+校验位异常    xUebern                 : BOOL;         //RBS已接收标志    xS_TypFrg               : BOOL;         //类型输入接收按钮    xS_UebPZ                : BOOL;         //校验位接收按钮    xHand                   : BOOL;         //手动接收标志    xAuto                   : BOOL;         //自动接收标志    arrSTyp_IO              : ARRAY[1..8] OF BOOL;  //工作站类型各位置正常    arrSTyp_NIO             : ARRAY[1..8] OF BOOL;  //工作站类型各位置异常    xSTyp_IO                : BOOL;         //工作站类型整体正常    xSTyp_NIO               : BOOL;         //工作站类型整体异常    iZyklus                 : INT := 1;     //循环计数器(优化周期)    iZyklus16               : INT := 1;     //循环计数器(16分频)    wData                   : WORD;         //工作站类型数据(内部)        _wData AT wData     : STRUCT                    IO              : BOOL;        //工作站类型有效标志        END_STRUCT;    arrCode_RBS             : ARRAY[1..9] OF INT; //RBS字符的Code39编码值    chrPZ                   : CHAR;         //计算出的校验位    iCharCode39             : INT;          //Code39编码总和    iMOD_39                 : INT;          //Code39编码总和模43结果    xCODE39_IO              : BOOL;         //Code39校验正常    xCODE39_NIO             : BOOL;         //Code39校验异常    R_TRIG_S_TypFrg_Q       : BOOL;         //xS_TypFrg的上升沿    xR_TRIG_S_TypFrg_Edge   : BOOL;         //xS_TypFrg的边沿记忆    R_TRIG_Uebern           : BOOL;         //xUebern的上升沿    xR_TRIG_Uebern          : BOOL;         //xUebern的边沿记忆    R_TRIG_Auto_Q           : BOOL;         //Auto的上升沿    xR_TRIG_Auto_Q_Edge     : BOOL;         //Auto的边沿记忆    tempDB_RBS              : STRUCT        //RBS数据块缓存        Z                   : ARRAY[1..8] OF STRUCT            Bez             : ARRAY[1..3] OF STRING[20]; //各位置标题(3种语言)            Z               : ARRAY[1..16] OF STRUCT                                    CH          : CHAR;        //字符                Frg         : BOOL;        //有效标志                Sicht_RBS   : INT;         //RBS可见性偏移                Bez         : ARRAY[1..3] OF STRING[30]; //字符描述(3种语言)            END_STRUCT;        END_STRUCT;    END_STRUCT;    tempDB_STyp             : STRUCT        //工作站类型数据块缓存        Typ                 : ARRAY[1..100] OF STRUCT            bMax            : BYTE;        //最大长度            bAct            : BYTE;        //实际长度            arrText         : ARRAY[1..8] OF CHAR; //类型字符数组            Data            : STRUCT                IO          : BOOL;        //类型有效标志            END_STRUCT;        END_STRUCT;    END_STRUCT;END_VAR```**解读**:  - 静态变量用于存储持久化状态(功能块调用间保持值),如`_dwVisuWerte1`/`_dwVisuWerte2`控制可视化界面的状态(颜色、闪烁等);`arrRBS`存储当前读取的毛坯代码字符;`tempDB_RBS`/`tempDB_STyp`缓存数据块内容(避免频繁读取DB);`arrCode_RBS`存储RBS字符的Code39编码(用于校验位计算)。  #### 四、代码主体解读##### 1. 数据块初始化与参数计算```scl(* 数据块读取 *)IF Init OR NOT xInit OR "Neustart" THEN    erg_SFC20:= BLKMOV(srcblk:= DB_RBS  , dstblk:= tempDB_RBS);  //将DB_RBS复制到缓存tempDB_RBS    erg_SFC20:= BLKMOV(srcblk:= DB_STyp , dstblk:= tempDB_STyp); //将DB_STyp复制到缓存tempDB_STyp(* 计算毛坯代码位数 *)    iRBSAnz := WORD_TO_INT(pDB_RBS.Anz) / 1666;  //pDB_RBS.Anz是DB_RBS的总长度,1666为单个位的长度(* 计算毛坯代码长度(带/不带校验位) *)    IF Cfg.X1 THEN  //Cfg.X1=1:不使用校验位        iRBSLen := iRBSAnz;    ELSE  //使用校验位:长度=位数+1        iRBSLen := iRBSAnz + 1;    END_IF;(* 计算工作站类型DB中的条目数 *)    iTypAnz := WORD_TO_INT(pDB_STyp.Anz) / 12;  //pDB_STyp.Anz是DB_STyp的总长度,12为单个条目的长度END_IF;```**解读**:  - 当`Init`触发、未初始化(`xInit=0`)或系统重启(`Neustart`)时,通过`BLKMOV`(块移动指令)将`DB_RBS`(毛坯代码数据块)和`DB_STyp`(工作站类型数据块)的数据缓存到`tempDB_RBS`和`tempDB_STyp`(减少对实际DB的访问)。  - 计算核心参数:`iRBSAnz`(毛坯代码的位数)、`iRBSLen`(带/不带校验位的总长度)、`iTypAnz`(工作站类型的条目数量)。  ##### 2. 配置RBS数据的ANY指针```scl(* 设置ANY指针到RBS数据 *)p_RBS.SyntaxId     := B#16#10;                     //ANY指针的语法ID固定为16#10p_RBS.DataType     := 02;                          //数据类型:02=BYTE(RBS为字符,按字节存储)p_RBS.DataCount    := INT_TO_WORD(iRBSLen);        //长度:RBS的总长度(含校验位) p_RBS.DBNR         := pRBS.DBNR;                   //DB编号:从RBS指针获取p_RBS.BZ           := pRBS.BZ;                     //区域指针:从RBS指针获取```**解读**:  - 配置`anyRBS`指针(`p_RBS`)指向实际的RBS数据,`SyntaxId=16#10`是西门子ANY指针的固定格式,`DataType=02`表示数据为字节类型,`DataCount`为RBS的长度。  ##### 3. 可视化按键评估```scl(******* 按键评估 ****************************************************************)IF PC_AKTIV = DWORD#16#00000000 THEN  //PC未激活时,软键输入清零    bVisuTasten := Byte#0;END_IF;xS_UebPZ    := (bVisuTasten = Byte#1);  //bVisuTasten=1:校验位接收按键xS_TypFrg   := (bVisuTasten = Byte#2);  //bVisuTasten=2:类型输入接收按键```**解读**:  - 读取可视化界面的软键输入(`bVisuTasten`),映射为具体功能:`xS_UebPZ`(校验位接收)和`xS_TypFrg`(类型输入接收)。  ##### 4. 上升沿检测```scl(******* 上升沿检测 ***************************************************************)R_TRIG_S_TypFrg_Q       := xS_TypFrg AND NOT xR_TRIG_S_TypFrg_Edge;  //xS_TypFrg的上升沿(单次触发)xR_TRIG_S_TypFrg_Edge   := xS_TypFrg;  //记忆xS_TypFrg的当前状态R_TRIG_Auto_Q           := Auto AND NOT xR_TRIG_Auto_Q_Edge;  //Auto的上升沿(单次触发)xR_TRIG_Auto_Q_Edge     := Auto;  //记忆Auto的当前状态```**解读**:  - 通过“当前值为1且前值为0”检测上升沿,确保`xS_TypFrg`(类型接收)和`Auto`(自动模式使能)的触发信号仅有效一次(避免持续触发)。  ##### 5. 重置接收标志```scl(******* 重置接收 ***************************************************************)IF FM_Reset OR (NOT Hand AND R_TRIG_Auto_Q) THEN    xUebern         := False;  //清除RBS已接收标志END_IF;```**解读**:  - 当`FM_Reset`(重置命令)触发,或切换到自动模式(`Hand=0`且`Auto`上升沿)时,清除`xUebern`(RBS已接收标志),允许重新接收RBS。  ##### 6. RBS接收(手动/自动模式)```scl(******* RBS接收 *****************************************************************)//手动RBS接收IF NOT xUebern AND Hand THEN  //未接收且手动模式使能    IF dwVisuWerte1.X15 THEN        //手动字符串输入接收标志触发        arrRBS      := strVisuWertRBS.arrText;  //从可视化字符串读取RBS字符        dwVisuWerte1.X15 := False;  //清除标志    ELSE         FOR iLauf := 1 TO iRBSAnz BY 1 DO  //循环读取各位置            IF iVisuTastenS[iLauf] >= 1 AND iVisuTastenS[iLauf] <= 16 THEN  //软键输入有效                arrRBS[iLauf] := tempDB_RBS.Z[iLauf].Z[iVisuTastenS[iLauf]].CH; //从缓存读取对应字符            ELSE                arrRBS[iLauf] := '*';  //无效输入用'*'表示            END_IF;        END_FOR;        IF NOT Cfg.X1 THEN //使用校验位时            IF xS_UebPZ AND xRBS_IO THEN //校验位接收按键触发且RBS有效                arrRBS[iRBSLen]   := chrPZ;  //用计算出的校验位填充            ELSIF arrRBS[iRBSLen] <> chrPZ THEN  //输入校验位与计算值不符                arrRBS[iRBSLen] := '*';  //标记异常            END_IF;        END_IF;    END_IF;//自动RBS接收ELSIF NOT xUebern AND Auto THEN  //未接收且自动模式使能    erg_SFC20 := BLKMOV(SRCBLK := anyRBS ,DSTBLK := arrRBS);  //从RBS数据块自动读取字符END_IF;    ```**解读**:  - **手动模式**:通过可视化界面输入RBS,支持两种方式:直接输入字符串(`dwVisuWerte1.X15`触发)或通过软键选择字符(`iVisuTastenS`),无效输入用`*`标记;若启用校验位,需匹配计算出的`chrPZ`。  - **自动模式**:通过`BLKMOV`从`anyRBS`指向的RBS数据块自动读取字符到`arrRBS`。  ##### 7. RBS预设位置评估(位置1)```scl(******* 评估RBS预设位置1 ********************************************************)anyDB_RBS1 := DB_RBS;  //指向原始DB_RBSanyDB_RBS2 := tempDB_RBS.Z[2];  //指向缓存中RBS的位置2IF Cfg.X0 THEN  //Cfg.X0=1:需评估DB_RBS的预设位置2-x    FOR i := 1 TO 16 BY 1 DO  //循环匹配位置1的字符        IF tempDB_RBS.Z[1].Z[i].CH = arrRBS[1] THEN  //位置1字符匹配            iSicht_RBS := tempDB_RBS.Z[1].Z[i].Sicht_RBS;  //获取可见性偏移            iBer_RBS   := 1666 * (iRBSAnz - 1);  //计算区域长度(位置2-x的总长度)                       p_DB_RBS1.DataCount := INT_TO_WORD(iBer_RBS);  //设置数据长度            //调整区域指针(指向位置2-x的起始地址)            p_DB_RBS1.BZ := 16#84000000 OR SHL(IN:=INT_TO_DWORD(1666 + (iBer_RBS * iSicht_RBS)),N:=3);             p_DB_RBS2.DataCount := INT_TO_WORD(iBer_RBS);  //缓存中位置2-x的长度            p_DB_RBS2.BZ := p_DB_RBS2.BZ OR 16#1000000;  //调整区域指针(从DB到DI)            erg_SFC20:= BLKMOV(srcblk:= anyDB_RBS1  , dstblk:= anyDB_RBS2);  //更新缓存中位置2-x的数据        END_IF;    END_FOR;END_IF;```**解读**:  - 当`Cfg.X0=1`时,需根据RBS位置1的字符匹配预设规则,动态更新位置2-x的数据(从`DB_RBS`复制到缓存`tempDB_RBS.Z[2]`),实现灵活的RBS结构适配。  ##### 8. 重置与初始化```scl(****** 重置 ***************************************************************************)IF NOT xUebern OR FM_Reset THEN  //未接收或重置时    arrRBS_IO       := arrTemp;  //清空RBS各位置正常标志    xRBS_IO         := False;  //RBS整体正常标志清零    xRBS_NIO        := False;  //RBS整体异常标志清零    xRBS_PZ_IO      := False;  //RBS+校验位正常标志清零    xRBS_PZ_NIO     := False;  //RBS+校验位异常标志清零    iVisuTastenS[1] := 0;  //软键输入值清零(位置1)    iVisuTastenS[2] := 0;  //位置2    iVisuTastenS[3] := 0;  //位置3    iVisuTastenS[4] := 0;  //位置4    iVisuTastenS[5] := 0;  //位置5    iVisuTastenS[6] := 0;  //位置6    iVisuTastenS[7] := 0;  //位置7    iVisuTastenS[8] := 0;  //位置8    CASE iRBSLen OF  //根据RBS长度初始化可视化字符串        4 : _strVisuWertRBS := '****';        5 : _strVisuWertRBS := '*****';        6 : _strVisuWertRBS := '******';        7 : _strVisuWertRBS := '*******';        8 : _strVisuWertRBS := '********';        9 : _strVisuWertRBS := '*********';    END_CASE;    _strVisuWertPZ  := '*';  //校验位可视化字符串初始化    arrSTyp_IO      := arrTemp;  //清空工作站类型各位置正常标志    xSTyp_IO        := False;  //工作站类型整体正常标志清零    xSTyp_NIO       := False;  //工作站类型整体异常标志清零    wData           := Word#0;  //工作站类型数据清零    xCODE39_IO      := False;  //Code39校验正常标志清零    xCODE39_NIO     := False;  //Code39校验异常标志清零END_IF;```**解读**:  - 当未接收RBS或`FM_Reset`触发时,重置所有与RBS、工作站类型相关的标志和变量,初始化可视化字符串(用`*`占位),确保下次接收前状态干净。  ##### 9. RBS有效性评估```scl(***** 评估毛坯代码 ******************************************************)IF (HAND OR Auto) AND NOT xUebern AND NOT FM_Reset THEN  //手动/自动使能、未接收、未重置    FOR i := 1 TO iRBSAnz BY 1 DO  //循环评估各位置        FOR iLauf := 1 TO 16 BY 1 DO  //匹配缓存中的有效字符            IF tempDB_RBS.Z[i].Z[iLauf].CH = arrRBS[i] THEN  //字符匹配                arrRBS_IO[i] := tempDB_RBS.Z[i].Z[iLauf].Frg;  //获取该字符的有效标志                IF arrRBS_IO[i] THEN  //字符有效                    iVisuTastenS[i] := iLauf;  //记录软键输入值                    strVisuWertRBS.arrText[i] := tempDB_RBS.Z[i].Z[iVisuTastenS[i]].CH;  //更新可视化字符                END_IF;                EXIT;  //匹配后退出内层循环            ELSIF tempDB_RBS.Z[i].Z[iLauf].CH = ' ' THEN  //遇到空格(结束符)                EXIT;            END_IF;                 END_FOR;        arrRBS_NIO[i] := NOT arrRBS_IO[i];  //异常标志=非正常标志    END_FOR;    xRBS_IO  := True;  //默认RBS整体正常    FOR i := 1 TO iRBSAnz BY 1 DO  //检查所有位置        xRBS_IO  := xRBS_IO AND arrRBS_IO[i];  //整体正常=所有位置正常        xRBS_NIO := NOT xRBS_IO;  //整体异常=非整体正常    END_FOR;END_IF;```**解读**:  - 评估RBS各位置的字符是否有效:循环匹配`tempDB_RBS`中定义的有效字符,设置`arrRBS_IO`(位置正常)和`arrRBS_NIO`(位置异常)。  - `xRBS_IO`为所有位置正常的“与”结果(全正常才为1),`xRBS_NIO`为其反值。  ##### 10. 校验位评估(Code39算法)```scl(***** 评估校验位 ***********************************************************)IF NOT Cfg.X1 AND xRBS_IO THEN  //启用校验位且RBS本身正常    strVisuWertRBS.arrText[iRBSLen] := arrRBS[iRBSLen];  //更新可视化校验位    FOR iLauf := 1 TO iRBSLen BY 1 DO  //将RBS字符转换为Code39编码        IF    strVisuWertRBS.arrText[iLauf] = '0' THEN arrCode_RBS[iLauf] := 0;        ELSIF strVisuWertRBS.arrText[iLauf] = '1' THEN arrCode_RBS[iLauf] := 1;        ELSIF strVisuWertRBS.arrText[iLauf] = '2' THEN arrCode_RBS[iLauf] := 2;                 ELSIF strVisuWertRBS.arrText[iLauf] = '3' THEN arrCode_RBS[iLauf] := 3;        ELSIF strVisuWertRBS.arrText[iLauf] = '4' THEN arrCode_RBS[iLauf] := 4;        ELSIF strVisuWertRBS.arrText[iLauf] = '5' THEN arrCode_RBS[iLauf] := 5;        ELSIF strVisuWertRBS.arrText[iLauf] = '6' THEN arrCode_RBS[iLauf] := 6;        ELSIF strVisuWertRBS.arrText[iLauf] = '7' THEN arrCode_RBS[iLauf] := 7;        ELSIF strVisuWertRBS.arrText[iLauf] = '8' THEN arrCode_RBS[iLauf] := 8;        ELSIF strVisuWertRBS.arrText[iLauf] = '9' THEN arrCode_RBS[iLauf] := 9;        ELSIF strVisuWertRBS.arrText[iLauf] = 'A' THEN arrCode_RBS[iLauf] := 10;        ELSIF strVisuWertRBS.arrText[iLauf] = 'B' THEN arrCode_RBS[iLauf] := 11;        ELSIF strVisuWertRBS.arrText[iLauf] = 'C' THEN arrCode_RBS[iLauf] := 12;        ELSIF strVisuWertRBS.arrText[iLauf] = 'D' THEN arrCode_RBS[iLauf] := 13;        ELSIF strVisuWertRBS.arrText[iLauf] = 'E' THEN arrCode_RBS[iLauf] := 14;        ELSIF strVisuWertRBS.arrText[iLauf] = 'F' THEN arrCode_RBS[iLauf] := 15;        ELSIF strVisuWertRBS.arrText[iLauf] = 'G' THEN arrCode_RBS[iLauf] := 16;        ELSIF strVisuWertRBS.arrText[iLauf] = 'H' THEN arrCode_RBS[iLauf] := 17;        ELSIF strVisuWertRBS.arrText[iLauf] = 'I' THEN arrCode_RBS[iLauf] := 18;        ELSIF strVisuWertRBS.arrText[iLauf] = 'J' THEN arrCode_RBS[iLauf] := 19;        ELSIF strVisuWertRBS.arrText[iLauf] = 'K' THEN arrCode_RBS[iLauf] := 20;        ELSIF strVisuWertRBS.arrText[iLauf] = 'L' THEN arrCode_RBS[iLauf] := 21;        ELSIF strVisuWertRBS.arrText[iLauf] = 'M' THEN arrCode_RBS[iLauf] := 22;        ELSIF strVisuWertRBS.arrText[iLauf] = 'N' THEN arrCode_RBS[iLauf] := 23;        ELSIF strVisuWertRBS.arrText[iLauf] = 'O' THEN arrCode_RBS[iLauf] := 24;        ELSIF strVisuWertRBS.arrText[iLauf] = 'P' THEN arrCode_RBS[iLauf] := 25;        ELSIF strVisuWertRBS.arrText[iLauf] = 'Q' THEN arrCode_RBS[iLauf] := 26;        ELSIF strVisuWertRBS.arrText[iLauf] = 'R' THEN arrCode_RBS[iLauf] := 27;        ELSIF strVisuWertRBS.arrText[iLauf] = 'S' THEN arrCode_RBS[iLauf] := 28;        ELSIF strVisuWertRBS.arrText[iLauf] = 'T' THEN arrCode_RBS[iLauf] := 29;        ELSIF strVisuWertRBS.arrText[iLauf] = 'U' THEN arrCode_RBS[iLauf] := 30;        ELSIF strVisuWertRBS.arrText[iLauf] = 'V' THEN arrCode_RBS[iLauf] := 31;        ELSIF strVisuWertRBS.arrText[iLauf] = 'W' THEN arrCode_RBS[iLauf] := 32;        ELSIF strVisuWertRBS.arrText[iLauf] = 'X' THEN arrCode_RBS[iLauf] := 33;        ELSIF strVisuWertRBS.arrText[iLauf] = 'Y' THEN arrCode_RBS[iLauf] := 34;        ELSIF strVisuWertRBS.arrText[iLauf] = 'Z' THEN arrCode_RBS[iLauf] := 35;        ELSIF strVisuWertRBS.arrText[iLauf] = '-' THEN arrCode_RBS[iLauf] := 36;        ELSIF strVisuWertRBS.arrText[iLauf] = '.' THEN arrCode_RBS[iLauf] := 37;        ELSIF strVisuWertRBS.arrText[iLauf] = ' ' THEN arrCode_RBS[iLauf] := 38;        ELSIF strVisuWertRBS.arrText[iLauf] ='$24'THEN arrCode_RBS[iLauf] := 39;        ELSIF strVisuWertRBS.arrText[iLauf] = '/' THEN arrCode_RBS[iLauf] := 40;        ELSIF strVisuWertRBS.arrText[iLauf] = '+' THEN arrCode_RBS[iLauf] := 41;        ELSIF strVisuWertRBS.arrText[iLauf] = '%' THEN arrCode_RBS[iLauf] := 42;        END_IF;     END_FOR;    iCharCode39 := 0;  //初始化编码总和    FOR i := 1 TO iRBSAnz BY 1 DO  //计算RBS位(不含校验位)的编码总和        iCharCode39 := iCharCode39 + arrCode_RBS[i];    END_FOR;    iMOD_39 := iCharCode39 MOD 43 ;  //总和模43(Code39校验规则)    //检查输入校验位是否与计算值匹配    IF arrCode_RBS[iRBSLen] = iMOD_39 AND strVisuWertRBS.arrText[iRBSLen] <> '*' THEN         xCODE39_IO  := True;  //校验正常        xCODE39_NIO := False;    ELSE        xCODE39_IO  := False;  //校验异常        xCODE39_NIO := True;    END_IF;    //根据模43结果确定校验位字符    CASE iMOD_39 OF        0  : chrPZ := '0';        1  : chrPZ := '1';              2  : chrPZ := '2';        3  : chrPZ := '3';        4  : chrPZ := '4';        5  : chrPZ := '5';        6  : chrPZ := '6';        7  : chrPZ := '7';        8  : chrPZ := '8';        9  : chrPZ := '9';        10 : chrPZ := 'A';        11 : chrPZ := 'B';        12 : chrPZ := 'C';        13 : chrPZ := 'D';        14 : chrPZ := 'E';        15 : chrPZ := 'F';        16 : chrPZ := 'G';        17 : chrPZ := 'H';        18 : chrPZ := 'I';        19 : chrPZ := 'J';        20 : chrPZ := 'K';        21 : chrPZ := 'L';        22 : chrPZ := 'M';        23 : chrPZ := 'N';        24 : chrPZ := 'O';        25 : chrPZ := 'P';        26 : chrPZ := 'Q';        27 : chrPZ := 'R';        28 : chrPZ := 'S';        29 : chrPZ := 'T';        30 : chrPZ := 'U';        31 : chrPZ := 'V';        32 : chrPZ := 'W';        33 : chrPZ := 'X';        34 : chrPZ := 'Y';        35 : chrPZ := 'Z';        36 : chrPZ := '-';        37 : chrPZ := '.';        38 : chrPZ := ' ';        39 : chrPZ := '$24';        40 : chrPZ := '/';        41 : chrPZ := '+';        42 : chrPZ := '%';    END_CASE;ELSE    chrPZ := '*';  //不启用校验位或RBS异常时,校验位无效END_IF;strVisuWertPZ.arrText[1] := chrPZ;  //更新可视化校验位(*RBS整体有效性(含校验位)*)xRBS_PZ_IO  := xRBS_IO AND (xCODE39_IO OR Cfg.X1);  //整体正常=RBS正常且(校验正常或不启用校验)xRBS_PZ_NIO := xRBS_NIO OR (xCODE39_NIO AND NOT Cfg.X1);  //整体异常=RBS异常或(校验异常且启用校验)```**解读**:  - 当启用校验位(`Cfg.X1=0`)且RBS本身正常(`xRBS_IO=1`)时,通过Code39算法计算校验位:    1. 将RBS字符映射为Code39编码(0-42);    2. 计算RBS位(不含校验位)的编码总和,对43取模(`iMOD_39`);    3. 模值对应的字符即为正确校验位(`chrPZ`),与输入校验位比对,设置`xCODE39_IO`(校验正常)。  - `xRBS_PZ_IO`为RBS整体有效性(含校验位),`xRBS_PZ_NIO`为其反值。  ##### 11. 工作站类型评估```scl(****** 评估工作站类型 **********************************************************)IF (HAND OR Auto) AND NOT xUebern AND NOT FM_Reset AND xRBS_PZ_IO THEN  //RBS有效时评估工作站类型    FOR iLauf := 1 TO iTypAnz BY 1 DO  //循环匹配工作站类型条目        FOR i := 1 TO iRBSAnz BY 1 DO  //匹配各位置字符            IF tempDB_STyp.Typ[iLauf].arrText[i] = arrRBS[i]  //字符完全匹配                OR tempDB_STyp.Typ[iLauf].arrText[i] = 'X' AND NOT cfg.X2  //占位符X(Cfg.X2=0)                OR tempDB_STyp.Typ[iLauf].arrText[i] = '~' AND cfg.X2  //占位符~(Cfg.X2=1)            THEN                arrSTyp_IO[i]  := True;  //该位置匹配            ELSE                EXIT;  //不匹配则退出内层循环            END_IF;                 END_FOR;        IF arrSTyp_IO[iRBSAnz] THEN  //所有位置都匹配            _wData  := tempDB_STyp.Typ[iLauf].Data;  //获取该类型的数据            EXIT;  //退出外层循环        END_IF;             END_FOR;    xSTyp_IO  := arrSTyp_IO[iRBSAnz];  //工作站类型正常=所有位置匹配    xSTyp_NIO := NOT xSTyp_IO;  //工作站类型异常=非正常END_IF;```**解读**:  - 当RBS有效(`xRBS_PZ_IO=1`)时,评估RBS是否匹配`tempDB_STyp`中定义的工作站类型:    - 支持精确匹配或占位符匹配(`X`或`~`,由`Cfg.X2`控制);    - 所有位置匹配时,`xSTyp_IO=1`(工作站类型正常),并获取对应数据`_wData`。  ##### 12. 接收确认```scl(* 接收确认 *)IF ((Auto AND NOT Hand) OR (Hand AND R_TRIG_S_TypFrg_Q AND NOT xUebern)) AND xRBS_PZ_IO AND NOT FM_Reset THEN    xUebern     := True;  //设置RBS已接收标志(自动模式或手动触发且RBS有效)ELSIF (Hand AND R_TRIG_S_TypFrg_Q AND xUebern) OR xRBS_PZ_NIO OR FM_Reset THEN    xUebern     := False;  //清除接收标志(手动触发已接收、RBS异常或重置)END_IF;//更新手动/自动接收标志R_TRIG_Uebern    := xUebern AND NOT xR_TRIG_Uebern;  //xUebern的上升沿xR_TRIG_Uebern   := xUebern;  //记忆xUebern状态IF R_TRIG_Uebern THEN  //接收成功时    xHand  := Hand;  //记录手动模式    xAuto  := NOT Hand;  //记录自动模式ELSIF NOT xUebern THEN  //未接收时    xHand  := False;    xAuto  := False;END_IF;```**解读**:  - 当满足以下条件时,设置`xUebern`(RBS已接收标志):    - 自动模式(`Auto=1`且`Hand=0`)且RBS有效;    - 手动模式(`Hand=1`)且触发`R_TRIG_S_TypFrg_Q`(类型接收上升沿)且RBS有效。  - 记录当前接收模式(`xHand`/`xAuto`)。  ##### 13. 输出变量赋值```scl(***** 输出 *************************************************************************)RBS_IO     := xRBS_PZ_IO;  //RBS正常=RBS+校验位正常RBS_NIO    := xRBS_PZ_NIO;  //RBS异常=RBS+校验位异常STypIO     := xSTyp_IO AND xUebern;  //工作站类型正常=类型正常且已接收STypNIO    := xSTyp_NIO AND xUebern;  //工作站类型异常=类型异常且已接收FM         := xUebern;  //RBS已接收标志//初始化RBS各位置输出(位编码)RBS_S1   := Word#0;RBS_S2   := Word#0;// ... 省略RBS_S3至RBS_S7 ...RBS_S8   := Word#0;Data     := Word#0;IF xUebern  THEN  //已接收时更新输出    IF iVisuTastenS[1] > 0 THEN RBS_S1 := ROL (IN:=WORD#2#0000_0000_1000_0000, N:=iVisuTastenS[1]); END_IF;  //位1编码    IF iVisuTastenS[2] > 0 THEN RBS_S2 := ROL (IN:=WORD#2#0000_0000_1000_0000, N:=iVisuTastenS[2]); END_IF;  //位2编码    // ... 省略RBS_S3至RBS_S8的编码 ...    Data     := wData;  //输出工作站类型数据END_IF;```**解读**:  - 输出变量与内部状态映射:`RBS_IO`/`RBS_NIO`反映RBS整体有效性,`STypIO`/`STypNIO`反映工作站类型有效性(仅在已接收时有效),`FM`为接收标志。  - `RBS_S1`至`RBS_S8`通过循环左移(`ROL`)将软键输入值编码为位信号,便于外部识别具体位置。  ##### 14. 数据块更新(RBS_S数据)```scl(* 设置ANY指针到RBS_S数据源 *)anyQRBS_S := Data;  //源为工作站类型数据p_QRBS_S.DataType  := Byte#4;  //数据类型:4=WORDp_QRBS_S.DataCount := INT_TO_WORD(iRBSAnz + 1);  //长度:RBS位数+1p_QRBS_S.BZ        := p_QRBS_S.BZ OR 16#1000000;  //调整区域指针(从DB到DI)(* 设置ANY指针到RBS_S数据目标 *)anyZRBS_S := DB_STyp;  //目标为工作站类型数据块p_ZRBS_S.DataType  := Byte#4;  //数据类型:4=WORDp_ZRBS_S.DataCount := INT_TO_WORD(iRBSAnz + 1);  //长度:RBS位数+1p_ZRBS_S.BZ        := SHL(IN:=pDB_STyp.Anz, N:=3) OR 16#84000000;  //计算目标区域指针erg_SFC20 := BLKMOV(SRCBLK := anyQRBS_S ,dstblk := anyZRBS_S);  //将RBS_S数据写入目标DB```**解读**:  - 配置指针将工作站类型数据(`Data`)写入`DB_STyp`(工作站类型数据块),实现数据持久化存储。  ##### 15. 循环周期优化```scl(* 循环时间优化 *)iZyklus16 := iZyklus16 + 1;  //16分频计数器IF iZyklus16 > 16 THEN    iZyklus16 := 1;    iZyklus := iZyklus + 1;  //主循环计数器    IF iZyklus > iRBSAnz THEN        iZyklus := 1;  //计数器回环(最大为RBS位数)    END_IF;END_IF;```**解读**:  - 通过分频计数器(`iZyklus16`)和主计数器(`iZyklus`)控制可视化更新频率,避免高频刷新占用过多资源。  ##### 16. 可视化文本更新```scl(* 列标题 *)strVisuText.S[iZyklus].Bez := tempDB_RBS.Z[iZyklus].Bez[Sprache];  //根据语言更新列标题(* 按键标题 *)strVisuText.S[iZyklus].Z[iZyklus16].Bez := tempDB_RBS.Z[iZyklus].Z[iZyklus16].Bez[Sprache];  //根据语言更新按键标题```**解读**:  - 根据当前语言(`Sprache`)和循环计数器,动态更新可视化界面的列标题和按键文本(支持多语言)。  ##### 17. 可视化状态与颜色控制```scl(******* 可视化数据 **************************************************)(**************************颜色编码表***********************************************)(*BK=黑, BU=蓝, GN=绿, GR=灰, LT=浅, WH=白, YE=黄, RD=红                            *)(*st=静态, bl=闪烁                                                                   *)(*HEX/INT  背景色        文本色                                                     *)(*H00/I00: 灰st         黑st                                                       *)(*H01/I01: 不可见                                                                   *)(*H02/I02: 绿st         黑st                                                       *)(*H03/I03: 蓝st         白st                                                       *)(*H04/I04: 红st         白st                                                       *)(*... 省略其他颜色编码 ...                                                          *)(****************************************************************************************)//可视化状态位配置dwVisuWerte1.X0  := Hand AND NOT xUebern AND NOT FM_Reset;  //手动输入使能dwVisuWerte1.X1  := Auto;  //自动模式使能dwVisuWerte1.X2  := Hand;  //手动模式使能dwVisuWerte1.X3  := xRBS_NIO AND NOT arrRBS_IO[1] OR (xSTyp_NIO AND NOT arrSTyp_IO[1]) AND NOT xUebern;  //RBS位1故障闪烁// ... 省略RBS位2至位8的故障闪烁配置 ...dwVisuWerte1.X11 := iRBSAnz >= 5;  //位5可见dwVisuWerte1.X12 := iRBSAnz >= 6;  //位6可见dwVisuWerte1.X13 := iRBSAnz >= 7;  //位7可见dwVisuWerte1.X14 := iRBSAnz >= 8;  //位8可见dwVisuWerte1.X15 := dwVisuWerte1.X15;  //手动RBS接收标志//RBS边框颜色(正常=绿,异常=红)bFarbKombi := byte#16#00;  //默认灰底黑字IF xRBS_PZ_IO THEN  //RBS正常    bFarbKombi := byte#16#02;  //绿底黑字ELSIF xRBS_PZ_NIO THEN  //RBS异常    bFarbKombi := byte#16#04;  //红底白字END_IF;dwVisuWerte1.B2 := bFarbKombi;  //更新可视化//校验位边框颜色(故障=红)bFarbKombi := byte#16#00;IF False THEN  //预留故障条件    bFarbKombi := byte#16#04;  //红底白字END_IF;dwVisuWerte1.B2 := dwVisuWerte1.B2 OR SHL(IN:=bFarbKombi,N:=4);  //高4位控制校验位边框// ... 省略其他可视化元素(符号边框、按钮颜色)的颜色配置 ...```**解读**:  - 配置可视化界面的状态位(如手动/自动模式、故障闪烁)和颜色(基于颜色编码表),直观反映系统状态(正常为绿,异常为红)。  ##### 18. 消息系统与故障处理```scl(****************************************************************************************)(*******************消息系统信号处理 *******************************)(***********************在SCL块末尾调用**********************************)TempPointerMsys       := Msys;  //消息系统指针TempPointerFlanken    := Msys.Flanken;  //边沿检测指针TempPointerMeldpuffer := ST_Meld;  //消息缓冲区指针pMeldFeld.BZ := pMeldFeld.BZ OR 16#1000000;  //调整区域指针(DB→DI)pMeldAbb.BZ  := pMeldAbb.BZ  OR 16#1000000;pMeldFeld.TYP := 1;  //数据类型=BOOLpMeldFeld.ANZ := 16;  //16个消息标志pMeldAbb.TYP  := 2;  //数据类型=BYTEpMeldAbb.ANZ  := 2;  //2个边沿检测字节//消息标志映射(故障源)MSYS.xF_1   :=  xRBS_NIO AND arrRBS_NIO[1];  //RBS位1异常MSYS.xF_2   :=  xRBS_NIO AND arrRBS_NIO[2];  //RBS位2异常// ... 省略RBS位3至位8的故障映射 ...MSYS.xF_9   :=  STypNIO;  //工作站类型无效MSYS.xF_10  :=  xCODE39_NIO;  //校验位异常MSYS.xF_11  :=  HAND AND NOT xUebern;  //手动输入激活//发送消息MeldSend(AufrufNr       := 1         ,Anz_Meld      := 11          ,pMeldFeld     := pMeldFeld.BZ         ,pMeldAbb      := pMeldAbb.BZ         ,MeldDB        := WORD_TO_INT(pMeldDBNR.DBNR)         ,AenderungsID  := AenderungsID         ,Integritaet   := xIntegritaet         ,Neustart      := Neustart         ); // 发送消息到消息系统xInit := True;  //初始化完成//故障/警告/维护消息汇总xStoe :=  Msys.xF_1    OR Msys.xF_2    OR Msys.xF_3    OR Msys.xF_4    OR Msys.xF_5    OR Msys.xF_6    OR Msys.xF_7    OR Msys.xF_8    OR Msys.xF_10;  //故障汇总DB_ARG.VisuSS.Station_Stoer:= DB_ARG.VisuSS.Station_Stoer OR xStoe;  //更新全局故障xWarn := Msys.xF_9 OR  Msys.xF_11;  //警告汇总DB_ARG.VisuSS.Station_Warn := DB_ARG.VisuSS.Station_Warn OR xWarn;  //更新全局警告xWart := False;  //维护消息(预留)DB_ARG.VisuSS.Station_Wart := DB_ARG.VisuSS.Station_Wart OR xWart;```**解读**:  - 将内部故障(如RBS位异常、校验位错误)映射到消息系统标志(`MSYS.xF_1`至`xF_11`),通过`MeldSend`发送到消息缓冲区(`ST_Meld`)。  - 汇总故障(`xStoe`)、警告(`xWarn`)并更新全局状态(`DB_ARG`),实现故障的集中监控。  ##### 19. 故障输出```scl(***** 汇总故障 *******************************************************************)Stoe := xStoe;  //输出汇总故障(***** 连锁故障 **************************************************************)VkStoe_Out := VkStoe_In OR xStoe;  //连锁故障=输入连锁故障OR内部故障```**解读**:  - `Stoe`输出内部汇总故障;`VkStoe_Out`输出连锁故障(包含外部输入故障和内部故障),用于故障级联传递。  #### 五、总结FB_Typ_VAR(FB529)是一个用于评估毛坯代码(RBS)和工作站类型的功能块,核心功能包括:  1. 支持手动/自动模式接收RBS,通过数据块缓存实现高效访问。  2. 对RBS进行有效性校验(含Code39校验位),评估各位置字符是否合法。  3. 匹配工作站类型(支持占位符`X`/`~`),判断是否与RBS匹配。  4. 丰富的可视化交互(多语言、颜色状态、软键输入)和故障消息系统,便于运维监控。  该功能块广泛应用于工业自动化场景(如汽车生产),确保毛坯代码与工作站类型的一致性,提高生产过程的可靠性。

部分详细解读:

1. 数据块初始化与参数计算

##### 1. 数据块初始化与参数计算```scl(* 数据块读取 *)IF Init OR NOT xInit OR "Neustart" THEN    erg_SFC20:= BLKMOV(srcblk:= DB_RBS  , dstblk:= tempDB_RBS);  //将DB_RBS复制到缓存tempDB_RBS    erg_SFC20:= BLKMOV(srcblk:= DB_STyp , dstblk:= tempDB_STyp); //将DB_STyp复制到缓存tempDB_STyp(* 计算毛坯代码位数 *)    iRBSAnz := WORD_TO_INT(pDB_RBS.Anz) / 1666;  //pDB_RBS.Anz是DB_RBS的总长度,1666为单个位的长度(* 计算毛坯代码长度(带/不带校验位) *)    IF Cfg.X1 THEN  //Cfg.X1=1:不使用校验位        iRBSLen := iRBSAnz;    ELSE  //使用校验位:长度=位数+1        iRBSLen := iRBSAnz + 1;    END_IF;(* 计算工作站类型DB中的条目数 *)    iTypAnz := WORD_TO_INT(pDB_STyp.Anz) / 12;  //pDB_STyp.Anz是DB_STyp的总长度,12为单个条目的长度END_IF;```

解读:

- 当`Init`触发、未初始化(`xInit=0`)或系统重启(`Neustart`)时,通过`BLKMOV`(块移动指令)将`DB_RBS`(毛坯代码数据块)和`DB_STyp`(工作站类型数据块)的数据缓存到`tempDB_RBS`和`tempDB_STyp`(减少对实际DB的访问)。

- 计算核心参数:`iRBSAnz`(毛坯代码的位数)、`iRBSLen`(带/不带校验位的总长度)、`iTypAnz`(工作站类型的条目数量)。

1.1:

erg_SFC20:=BLKMOV(srcblk:= DB_STyp , dstblk:= tempDB_STyp); //将DB_STyp复制到缓存tempDB_STyp

两个结构不同,目的是将原来的字符串拆分开

bMax是复制的字符串最大值,

bAct 字符串当前长度,

因为字符串前面两个字节是隐藏的,所以在拆分的时候要写出来

1.2:

(* 计算车型代码位数 *)

iRBSAnz := WORD_TO_INT(pDB_RBS.Anz) / 1666; //pDB_RBS.Anz是DB_RBS的总长度,1666为单个位的长度

4代表四位车型码,四组

1.3:

ELSE  //使用校验位:长度=位数+1

iRBSLen := iRBSAnz + 1;

此时+1  加一位代表着第五位的校验位

1.4:

iTypAnz := WORD_TO_INT(pDB_STyp.Anz) /12; //pDB_STyp.Anz是DB_STyp的总长度,12为单个条目的长度

48组数据

FB530的STyp结构总长度为576(16进制240)  除以12(每组车型12个字节占一组)

2. 配置RBS数据的ANY指针

(* 设置ANY指针到RBS数据 *)p_RBS.SyntaxId     := B#16#10;                     //ANY指针的语法ID固定为16#10p_RBS.DataType     := 02;                          //数据类型:02=BYTE(RBS为字符,按字节存储)p_RBS.DataCount    := INT_TO_WORD(iRBSLen);        //长度:RBS的总长度(含校验位) p_RBS.DBNR         := pRBS.DBNR;                   //DB编号:从RBS指针获取p_RBS.BZ           := pRBS.BZ;                     //区域指针:从RBS指针获取

解读:

- 配置`anyRBS`指针(`p_RBS`)指向实际的RBS数据,`SyntaxId=16#10`是西门子ANY指针的固定格式,`DataType=02`表示数据为字节类型,`DataCount`为RBS的长度。

DataCount:重复系数,只复制5个数据

输入数据RBS、DB2389.DBB89

2c8 —0010 1100 1000  —字地址89.0

(包含了字节地址与后三个位地址)

6. RBS接收(手动/自动模式)

(******* RBS接收 *****************************************************************)//手动RBS接收IF NOT xUebern AND Hand THEN  //未接收且手动模式使能    IF dwVisuWerte1.X15 THEN        //手动字符串输入接收标志触发        arrRBS      := strVisuWertRBS.arrText;  //从可视化字符串读取RBS字符        dwVisuWerte1.X15 := False;  //清除标志    ELSE         FOR iLauf := 1 TO iRBSAnz BY 1 DO  //循环读取各位置            IF iVisuTastenS[iLauf] >= 1 AND iVisuTastenS[iLauf] <= 16 THEN  //软键输入有效                arrRBS[iLauf] := tempDB_RBS.Z[iLauf].Z[iVisuTastenS[iLauf]].CH; //从缓存读取对应字符            ELSE                arrRBS[iLauf] := '*';  //无效输入用'*'表示            END_IF;        END_FOR;        IF NOT Cfg.X1 THEN //使用校验位时            IF xS_UebPZ AND xRBS_IO THEN //校验位接收按键触发且RBS有效                arrRBS[iRBSLen]   := chrPZ;  //用计算出的校验位填充            ELSIF arrRBS[iRBSLen] <> chrPZ THEN  //输入校验位与计算值不符                arrRBS[iRBSLen] := '*';  //标记异常            END_IF;        END_IF;    END_IF;//自动RBS接收ELSIF NOT xUebern AND Auto THEN  //未接收且自动模式使能    erg_SFC20 := BLKMOV(SRCBLK := anyRBS ,DSTBLK := arrRBS);  //从RBS数据块自动读取字符END_IF;    

解读:

- 手动模式:通过可视化界面输入RBS,支持两种方式:直接输入字符串(`dwVisuWerte1.X15`触发)或通过软键选择字符(`iVisuTastenS`),无效输入用`*`标记;若启用校验位,需匹配计算出的`chrPZ`。

- 自动模式:通过`BLKMOV`从`anyRBS`指向的RBS数据块自动读取字符到`arrRBS`。

6.1:

IFiVisuTastenS[iLauf] >=1 AND iVisuTastenS[iLauf] <= 16 THEN //软键输入有效

iVisuTastenS数组为手动输入的数据

6.2:

arrRBS[iLauf] := tempDB_RBS.Z[iLauf].Z[iVisuTastenS[iLauf]].CH;//从缓存读取对应字符

iVisuTastenS[iLauf]

 

arrRBS[iLauf]

arrRBS[iRBSLen]   := chrPZ;  //用计算出的校验位填充

6.3:

erg_SFC20 :=BLKMOV(SRCBLK := anyRBS ,DSTBLK := arrRBS);  //从RBS数据块自动读取字符

由输入RBS 传入

9. RBS有效性评估

(***** 评估毛坯代码 ******************************************************)IF (HAND OR Auto) AND NOT xUebern AND NOT FM_Reset THEN  //手动/自动使能、未接收、未重置    FOR i := 1 TO iRBSAnz BY 1 DO  //循环评估各位置        FOR iLauf := 1 TO 16 BY 1 DO  //匹配缓存中的有效字符            IF tempDB_RBS.Z[i].Z[iLauf].CH = arrRBS[i] THEN  //字符匹配                arrRBS_IO[i] := tempDB_RBS.Z[i].Z[iLauf].Frg;  //获取该字符的有效标志                IF arrRBS_IO[i] THEN  //字符有效                    iVisuTastenS[i] := iLauf;  //记录软键输入值                    strVisuWertRBS.arrText[i] := tempDB_RBS.Z[i].Z[iVisuTastenS[i]].CH;  //更新可视化字符                END_IF;                EXIT;  //匹配后退出内层循环            ELSIF tempDB_RBS.Z[i].Z[iLauf].CH = ' ' THEN  //遇到空格(结束符)                EXIT;            END_IF;                 END_FOR;        arrRBS_NIO[i] := NOT arrRBS_IO[i];  //异常标志=非正常标志    END_FOR;    xRBS_IO  := True;  //默认RBS整体正常    FOR i := 1 TO iRBSAnz BY 1 DO  //检查所有位置        xRBS_IO  := xRBS_IO AND arrRBS_IO[i];  //整体正常=所有位置正常        xRBS_NIO := NOT xRBS_IO;  //整体异常=非整体正常    END_FOR;END_IF;```

解读:

- 评估RBS各位置的字符是否有效:循环匹配`tempDB_RBS`中定义的有效字符,设置`arrRBS_IO`(位置正常)和`arrRBS_NIO`(位置异常)。

-`xRBS_IO`为所有位置正常的“与”结果(全正常才为1),`xRBS_NIO`为其反值。

9.1

arrRBS_IO[i]

9.2

strVisuWertRBS.arrText[i] :=tempDB_RBS.Z[i].Z[iVisuTastenS[i]].CH;  //更新可视化字符

注意这里只存入前四个数据,校验位由下面的程序传入

10. 校验位评估(Code39算法)

(***** 评估校验位 ***********************************************************)IF NOT Cfg.X1 AND xRBS_IO THEN  //启用校验位且RBS本身正常    strVisuWertRBS.arrText[iRBSLen] := arrRBS[iRBSLen];  //更新可视化校验位    FOR iLauf := 1 TO iRBSLen BY 1 DO  //将RBS字符转换为Code39编码        IF    strVisuWertRBS.arrText[iLauf] = '0' THEN arrCode_RBS[iLauf] := 0;        ELSIF strVisuWertRBS.arrText[iLauf] = '1' THEN arrCode_RBS[iLauf] := 1;        ELSIF strVisuWertRBS.arrText[iLauf] = '2' THEN arrCode_RBS[iLauf] := 2;                 ELSIF strVisuWertRBS.arrText[iLauf] = '3' THEN arrCode_RBS[iLauf] := 3;        ELSIF strVisuWertRBS.arrText[iLauf] = '4' THEN arrCode_RBS[iLauf] := 4;        ELSIF strVisuWertRBS.arrText[iLauf] = '5' THEN arrCode_RBS[iLauf] := 5;        ELSIF strVisuWertRBS.arrText[iLauf] = '6' THEN arrCode_RBS[iLauf] := 6;        ELSIF strVisuWertRBS.arrText[iLauf] = '7' THEN arrCode_RBS[iLauf] := 7;        ELSIF strVisuWertRBS.arrText[iLauf] = '8' THEN arrCode_RBS[iLauf] := 8;        ELSIF strVisuWertRBS.arrText[iLauf] = '9' THEN arrCode_RBS[iLauf] := 9;        ELSIF strVisuWertRBS.arrText[iLauf] = 'A' THEN arrCode_RBS[iLauf] := 10;        ELSIF strVisuWertRBS.arrText[iLauf] = 'B' THEN arrCode_RBS[iLauf] := 11;        ELSIF strVisuWertRBS.arrText[iLauf] = 'C' THEN arrCode_RBS[iLauf] := 12;        ELSIF strVisuWertRBS.arrText[iLauf] = 'D' THEN arrCode_RBS[iLauf] := 13;        ELSIF strVisuWertRBS.arrText[iLauf] = 'E' THEN arrCode_RBS[iLauf] := 14;        ELSIF strVisuWertRBS.arrText[iLauf] = 'F' THEN arrCode_RBS[iLauf] := 15;        ELSIF strVisuWertRBS.arrText[iLauf] = 'G' THEN arrCode_RBS[iLauf] := 16;        ELSIF strVisuWertRBS.arrText[iLauf] = 'H' THEN arrCode_RBS[iLauf] := 17;        ELSIF strVisuWertRBS.arrText[iLauf] = 'I' THEN arrCode_RBS[iLauf] := 18;        ELSIF strVisuWertRBS.arrText[iLauf] = 'J' THEN arrCode_RBS[iLauf] := 19;        ELSIF strVisuWertRBS.arrText[iLauf] = 'K' THEN arrCode_RBS[iLauf] := 20;        ELSIF strVisuWertRBS.arrText[iLauf] = 'L' THEN arrCode_RBS[iLauf] := 21;        ELSIF strVisuWertRBS.arrText[iLauf] = 'M' THEN arrCode_RBS[iLauf] := 22;        ELSIF strVisuWertRBS.arrText[iLauf] = 'N' THEN arrCode_RBS[iLauf] := 23;        ELSIF strVisuWertRBS.arrText[iLauf] = 'O' THEN arrCode_RBS[iLauf] := 24;        ELSIF strVisuWertRBS.arrText[iLauf] = 'P' THEN arrCode_RBS[iLauf] := 25;        ELSIF strVisuWertRBS.arrText[iLauf] = 'Q' THEN arrCode_RBS[iLauf] := 26;        ELSIF strVisuWertRBS.arrText[iLauf] = 'R' THEN arrCode_RBS[iLauf] := 27;        ELSIF strVisuWertRBS.arrText[iLauf] = 'S' THEN arrCode_RBS[iLauf] := 28;        ELSIF strVisuWertRBS.arrText[iLauf] = 'T' THEN arrCode_RBS[iLauf] := 29;        ELSIF strVisuWertRBS.arrText[iLauf] = 'U' THEN arrCode_RBS[iLauf] := 30;        ELSIF strVisuWertRBS.arrText[iLauf] = 'V' THEN arrCode_RBS[iLauf] := 31;        ELSIF strVisuWertRBS.arrText[iLauf] = 'W' THEN arrCode_RBS[iLauf] := 32;        ELSIF strVisuWertRBS.arrText[iLauf] = 'X' THEN arrCode_RBS[iLauf] := 33;        ELSIF strVisuWertRBS.arrText[iLauf] = 'Y' THEN arrCode_RBS[iLauf] := 34;        ELSIF strVisuWertRBS.arrText[iLauf] = 'Z' THEN arrCode_RBS[iLauf] := 35;        ELSIF strVisuWertRBS.arrText[iLauf] = '-' THEN arrCode_RBS[iLauf] := 36;        ELSIF strVisuWertRBS.arrText[iLauf] = '.' THEN arrCode_RBS[iLauf] := 37;        ELSIF strVisuWertRBS.arrText[iLauf] = ' ' THEN arrCode_RBS[iLauf] := 38;        ELSIF strVisuWertRBS.arrText[iLauf] ='$24'THEN arrCode_RBS[iLauf] := 39;        ELSIF strVisuWertRBS.arrText[iLauf] = '/' THEN arrCode_RBS[iLauf] := 40;        ELSIF strVisuWertRBS.arrText[iLauf] = '+' THEN arrCode_RBS[iLauf] := 41;        ELSIF strVisuWertRBS.arrText[iLauf] = '%' THEN arrCode_RBS[iLauf] := 42;        END_IF;     END_FOR;    iCharCode39 := 0;  //初始化编码总和    FOR i := 1 TO iRBSAnz BY 1 DO  //计算RBS位(不含校验位)的编码总和        iCharCode39 := iCharCode39 + arrCode_RBS[i];    END_FOR;    iMOD_39 := iCharCode39 MOD 43 ;  //总和模43(Code39校验规则)    //检查输入校验位是否与计算值匹配    IF arrCode_RBS[iRBSLen] = iMOD_39 AND strVisuWertRBS.arrText[iRBSLen] <> '*' THEN         xCODE39_IO  := True;  //校验正常        xCODE39_NIO := False;    ELSE        xCODE39_IO  := False;  //校验异常        xCODE39_NIO := True;    END_IF;    //根据模43结果确定校验位字符    CASE iMOD_39 OF        0  : chrPZ := '0';        1  : chrPZ := '1';              2  : chrPZ := '2';        3  : chrPZ := '3';        4  : chrPZ := '4';        5  : chrPZ := '5';        6  : chrPZ := '6';        7  : chrPZ := '7';        8  : chrPZ := '8';        9  : chrPZ := '9';        10 : chrPZ := 'A';        11 : chrPZ := 'B';        12 : chrPZ := 'C';        13 : chrPZ := 'D';        14 : chrPZ := 'E';        15 : chrPZ := 'F';        16 : chrPZ := 'G';        17 : chrPZ := 'H';        18 : chrPZ := 'I';        19 : chrPZ := 'J';        20 : chrPZ := 'K';        21 : chrPZ := 'L';        22 : chrPZ := 'M';        23 : chrPZ := 'N';        24 : chrPZ := 'O';        25 : chrPZ := 'P';        26 : chrPZ := 'Q';        27 : chrPZ := 'R';        28 : chrPZ := 'S';        29 : chrPZ := 'T';        30 : chrPZ := 'U';        31 : chrPZ := 'V';        32 : chrPZ := 'W';        33 : chrPZ := 'X';        34 : chrPZ := 'Y';        35 : chrPZ := 'Z';        36 : chrPZ := '-';        37 : chrPZ := '.';        38 : chrPZ := ' ';        39 : chrPZ := '$24';        40 : chrPZ := '/';        41 : chrPZ := '+';        42 : chrPZ := '%';    END_CASE;ELSE    chrPZ := '*';  //不启用校验位或RBS异常时,校验位无效END_IF;strVisuWertPZ.arrText[1] := chrPZ;  //更新可视化校验位(*RBS整体有效性(含校验位)*)xRBS_PZ_IO  := xRBS_IO AND (xCODE39_IO OR Cfg.X1);  //整体正常=RBS正常且(校验正常或不启用校验)xRBS_PZ_NIO := xRBS_NIO OR (xCODE39_NIO AND NOT Cfg.X1);  //整体异常=RBS异常或(校验异常且启用校验)

解读:

- 当启用校验位(`Cfg.X1=0`)且RBS本身正常(`xRBS_IO=1`)时,通过Code39算法计算校验位:

1. 将RBS字符映射为Code39编码(0-42);

2. 计算RBS位(不含校验位)的编码总和,对43取模(`iMOD_39`);

3. 模值对应的字符即为正确校验位(`chrPZ`),与输入校验位比对,设置`xCODE39_IO`(校验正常)。

-`xRBS_PZ_IO`为RBS整体有效性(含校验位),`xRBS_PZ_NIO`为其反值。

10.1

strVisuWertPZ.arrText[1] := chrPZ;  //更新可视化校验位

14. 数据块更新(RBS_S数据)

(* 设置ANY指针到RBS_S数据源 *)anyQRBS_S := Data;  //源为工作站类型数据p_QRBS_S.DataType  := Byte#4;  //数据类型:4=WORDp_QRBS_S.DataCount := INT_TO_WORD(iRBSAnz + 1);  //长度:RBS位数+1p_QRBS_S.BZ        := p_QRBS_S.BZ OR 16#1000000;  //调整区域指针(从DB到DI)(* 设置ANY指针到RBS_S数据目标 *)anyZRBS_S := DB_STyp;  //目标为工作站类型数据块p_ZRBS_S.DataType  := Byte#4;  //数据类型:4=WORDp_ZRBS_S.DataCount := INT_TO_WORD(iRBSAnz + 1);  //长度:RBS位数+1p_ZRBS_S.BZ        := SHL(IN:=pDB_STyp.Anz, N:=3) OR 16#84000000;  //计算目标区域指针erg_SFC20 := BLKMOV(SRCBLK := anyQRBS_S ,dstblk := anyZRBS_S);  //将RBS_S数据写入目标DB

解读:

- 配置指针将工作站类型数据(`Data`)写入`DB_STyp`(工作站类型数据块),实现数据持久化存储。

将功能块输出Data以下的五个字的数据复制到DB530.Data结构开始的五个字

监控数据:

Data数据等于16#0100,iRBSAnz等于4,p_QRBS_S.BZ数据等于16#85000130,DB_STyp为输入管脚传入的any指针数据,

详细解读:

这段代码的核心功能是通过SCL 的 ANY 指针配置,使用块移动指令(BLKMOV/SFC20)将源数据区域的内容复制到目标数据区域,本质是实现结构化数据的批量传输。结合你提供的具体参数(Data=16#0100、iRBSAnz=4、p_QRBS_S.BZ=16#85000130),我们可以分步骤解析如下:

一、背景知识:ANY 指针与 BLKMOV

在西门子 PLC 编程中:

ANY 指针是一种灵活的数据类型,用于描述 “一段连续数据的位置、类型和长度”,其结构包含:数据类型(DataType)、数据长度(DataCount)、存储区域指针(BZ,即 Bereichszeiger)等。

BLKMOV(SFC20) 是块移动指令,功能是将SRCBLK(源地址)指向的连续数据,复制到DSTBLK(目标地址),复制的长度由 ANY 指针中的DataCount决定。

逐段解析代码逻辑

1. 配置源数据的 ANY 指针(anyQRBS_S)

scl

(* Anypointer auf Quelle RBS_S Daten setzten *)

anyQRBS_S := Data;  // 源数据的基础地址指向Data变量

p_QRBS_S.DataType  :=Byte#4;  // 数据类型为WORD(16位)

p_QRBS_S.DataCount:=INT_TO_WORD(iRBSAnz +1);  // 复制的长度:iRBSAnz=4 → 4+1=5个数据

p_QRBS_S.BZ        := p_QRBS_S.BZOR16#1000000;  // 修正存储区域指针

anyQRBS_S := Data:

Data是 FB 的输出变量(WORD 类型,值为 16#0100),这句的作用是将源 ANY 指针的 “基础地址” 绑定到Data所在的内存位置(即Data的地址作为源数据的起始地址)。

p_QRBS_S.DataType:=Byte#4:

西门子中,DataType是数据类型编码,Byte#4对应WORD 类型(16 位无符号整数)。这表示要复制的数据是 “WORD 类型”。

p_QRBS_S.DataCount:=5:

iRBSAnz=4,因此iRBSAnz +1=5,表示要复制5 个 WORD(总长度 =5×2 字节 =10 字节)。

p_QRBS_S.BZ:=16#84000130OR16#1000000:

得出数据16#85000130:修正为背景 DB 区域

• 区域指针(BZ)的作用:32 位值,最高字节表示存储区域,低 24 位表示地址偏移(以位为单位)。

• 原始p_QRBS_S.BZ=16#84000130:最高字节84表示 “全局 DB”,低 24 位000130表示地址偏移为0x130位。

• 执行OR 16#1000000后,结果为16#85000130:最高字节85表示 “FB 的背景 DB”(84 | 1=85),低 24 位保持000130(地址偏移不变)。

• 最终含义:源数据位于FB 的背景 DB 中,起始地址偏移为0x130位(换算为字节:0x130 ÷ 8= 0x19字节,即背景 DB 的第 25 个字节)。

在西门子 PLC 的块移动逻辑中,Data在这里代表的是 “源数据的起始地址”,而不是 “唯一的数据内容”。具体来说,“复制 5 个WORD” 是从Data的地址开始,连续读取 5 个 WORD 类型的内存单元,Data本身是这 5 个 WORD 中的第一个。

第 1 个 WORD:Data本身(地址DB2390.DBW38,值 = 16#0100)

第 2 个WORD:Data地址 + 2 字节(地址DB2390.DBW40,值 = 未知,取决于后续变量)

第 3 个WORD:Data地址 + 4 字节(地址DB2390.DBW42)

第 4 个WORD:Data地址 + 6 字节(地址DB2390.DBW44)

第 5 个WORD:Data地址 + 8 字节(地址DB2390.DBW46)

2. 配置目标数据的 ANY 指针(anyZRBS_S)

scl

(* Anypointer auf Ziel RBS_S Daten setzten *)

anyZRBS_S := DB_STyp;  // 目标地址绑定到输入的DB_STyp(ANY指针)

p_ZRBS_S.DataType  :=Byte#4;  // 数据类型与源一致:WORD

p_ZRBS_S.DataCount:=INT_TO_WORD(iRBSAnz +1);  // 复制长度与源一致:5个WORD

p_ZRBS_S.BZ        :=SHL(IN:=pDB_STyp.Anz, N:=3) OR16#84000000;  // 计算目标区域指针

anyZRBS_S := DB_STyp:

DB_STyp是 FB 的输入变量(ANY 类型),表示目标数据所在的数据库(如某个全局 DB),这句将目标 ANY 指针绑定到DB_STyp指向的数据库。

p_ZRBS_S.DataType:=Byte#4:

与源数据类型保持一致(WORD),确保数据格式匹配。

p_ZRBS_S.DataCount:=5:

与源数据长度一致(5 个 WORD),确保复制的数据量相同。

p_ZRBS_S.BZ的计算:

16#84000000是西门子存储区域编码,表示 “全局数据块(Global DB)”;

SHL(IN:=pDB_STyp.Anz, N:=3):pDB_STyp.Anz是DB_STyp中定义的 “数据长度”(WORD 类型),左移 3 位等价于 “乘以 8”(将字节地址转换为位地址偏移,西门子中地址以位为最小单位);

最终BZ的含义:目标数据位于全局 DB 中,起始地址偏移为pDB_STyp.Anz × 8。

目标地址:

第 1 个 WORD:地址DB530.DBW576)

第 2 个WORD:地址DB530.DBW578)

第 3 个WORD:地址DB530.DBW580)

第 4 个WORD:地址DB530.DBW582)

第 5 个WORD:地址DB530.DBW584)

3. 执行数据复制(BLKMOV)

scl

erg_SFC20 := BLKMOV(SRCBLK := anyQRBS_S ,dstblk := anyZRBS_S);

功能:调用块移动指令,将anyQRBS_S指向的源数据(5 个 WORD)复制到anyZRBS_S指向的目标地址。

具体传输内容:

源数据以Data(16#0100)为起始,连续 5 个 WORD(假设后续 4 个 WORD 的值为Data+1、Data+2、Data+3、Data+4),最终复制到DB_STyp指定的全局 DB 中。

erg_SFC20:返回值,0表示复制成功,非 0 表示失败(如地址无效、长度不匹配等)。

我找到一个博途的vass06程序,通过博途监控程序可以详细看出此时传输的是地址指针

大众汽车

大众汽车

大众汽车集团是中国汽车工业最早、最成功的国际合作伙伴之一,伴随中国汽车工业成长近四十年。大众汽车集团(中国)始终致力于成为中国社会最值得信赖的合作伙伴,在为消费者提供可靠、高质量产品与服务的同时,更以支持中国社会的可持续发展作为重要己任。

大众汽车集团是中国汽车工业最早、最成功的国际合作伙伴之一,伴随中国汽车工业成长近四十年。大众汽车集团(中国)始终致力于成为中国社会最值得信赖的合作伙伴,在为消费者提供可靠、高质量产品与服务的同时,更以支持中国社会的可持续发展作为重要己任。收起

查看更多

相关推荐