前几天我们对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。 ?
#### 二、功能块基本信息
```scl
FUNCTION_BLOCK FB_Typ_VAR ? ?//FB529
TITLE ? =?'Version 3.1.03'
VERSION :?'3.1'
AUTHOR ?: VASS_V05
NAME ? ?: TYPVAR
FAMILY ?: TYPVAR
```
**解读**: ?
- 定义功能块`FB_Typ_VAR`,编号`FB529`,版本3.1.03,作者VASS_V05,名称TYPVAR,属于TYPVAR家族(功能块组)。 ?
#### 三、变量声明
##### 1. 输入变量(VAR_INPUT)
```scl
VAR_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)
```scl
VAR_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)
```scl
VAR_IN_OUT
? ? ST_Meld ? ? ? ? ? ? ? ? : Meldungspuffer; ??//消息缓冲区(消息结构体)
END_VAR
```
**解读**: ?
- `ST_Meld`:消息缓冲区,用于传递故障/状态消息(与消息系统交互)。 ?
##### 4. 临时变量(VAR_Temp)
```scl
VAR_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)
```scl
VAR
? ? _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#10
p_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_RBS
anyDB_RBS2 := tempDB_RBS.Z[2]; ?//指向缓存中RBS的位置2
IF 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=WORD
p_QRBS_S.DataCount :=?INT_TO_WORD(iRBSAnz +?1); ?//长度:RBS位数+1
p_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=WORD
p_ZRBS_S.DataCount :=?INT_TO_WORD(iRBSAnz +?1); ?//长度:RBS位数+1
p_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; ?//数据类型=BOOL
pMeldFeld.ANZ :=?16; ?//16个消息标志
pMeldAbb.TYP ?:=?2; ?//数据类型=BYTE
pMeldAbb.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#10
p_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=WORD
p_QRBS_S.DataCount := INT_TO_WORD(iRBSAnz +?1); ?//长度:RBS位数+1
p_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=WORD
p_ZRBS_S.DataCount := INT_TO_WORD(iRBSAnz +?1); ?//长度:RBS位数+1
p_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程序,通过博途监控程序可以详细看出此时传输的是地址指针