9.1 位逻辑指令
位逻辑指令处理布尔值“1”和“0”的逻辑变化。MetaFacture 提供的位逻辑指令包括基本的逻辑运算,置位/复位优先触发器及上升/下降沿检测指令,如表 9-1 所列举。
表 9-1 位逻辑指令的图形化与文本化指令表
|
位逻辑指令
|
图形化语言
|
文本化语言
|
说明
|
|
位逻辑指令
|
![]() |
AND
|
与
|
![]() |
OR
|
或
|
|
![]() |
NOT
|
非
|
|
![]() |
XOR
|
异或
|
|
![]() |
SR
|
置为优先触发器
|
|
![]() |
RS
|
复位优先触发器
|
|
![]() |
R_TRIG
|
上升沿触发
|
|
![]() |
F_TRIG
|
下降沿触发
|
)
9.1.1 基本逻辑指令
基本位逻辑指令包括有“与”、“或”、“非”、“异或”。在 MetaFacture 中,从功能上分可以分为:按位逻辑运算及布尔逻辑运算。
按位逻辑运算:对两个整型数据的相应位逐一进行布尔逻辑运算,并返回兼容的整数结果。
布尔逻辑运算:对两个布尔类型数据执行逻辑运算。
-
按位“与”AND
功能:按位“与”运算指令是比较两个整数的相应位。当两个数的对应位都是 1 时,返回相应的结果位是“1”;当两个整数的相应位都是“0”或者其中一个位是“0”时,则返回相应的结果位是“0”。其“与”逻辑如表 9-2 所示。
表9-2 “与”指令逻辑关系表
|
输入1
|
输入2
|
结果
|
|
0
|
0
|
0
|
|
0
|
1
|
0
|
|
1
|
0
|
0
|
|
1
|
1
|
1
|
【例 9.1】创建一个POU,声明两个整形变量iVar1和iVar2,分别对其进行赋值1和85,并对两个变量进行按位与运算,输出结果至iResult,变量声明如下所示,CFC编程代码如图9.2所示。
VAR
iResult :INT;
iVar1: INT := 1;
iVar2: INT := 85;
END_VAR

图9.1 按位“与”逻辑指令程序举例

图9.2 按位与运算程序图
10 进制数 1 对应 2 进制数为 0000 0001,10 进制数 85 对应 2 进制数为 0101 0101。根据按位与运算的定义,将每一个独立位逐一进行“与”运算,得出最终的结果 0000 0001,即 10 进制数值 1,见图 9.1 所示。
-
布尔“与”AND
功能:布尔“与”运算用于计算两个布尔表达式的“与”结果。当两个布尔表达式的结果都为真时,则返回为真,其中只要有一个为假时,则返回为假。
【例 9.2】创建一个 POU,利用布尔“与”运算,判断运算返回值,程序如图 9.3 所示。
VAR
iVar1: INT := 30;
bVar1: BOOL := FALSE;
iResult: BOOL;
END_VAR

图 9.3 布尔与运算 CFC 程序图
由于 30 的确小于 80,故程序上半部条件为真,但是 bVar1 的默认值为 FALSE,故 0 与 1 的结果为 0,程序的运行结果是 iResult 为 FALSE。
-
按位“或”OR
功能:按位“或”运算指令是比较两个整数的相应位。 当两个数的对应位有一个是“1”或者都是“1”时,返回相应的结果位为“1”。当两个整数的相应位都是“0”时,则返回相应的结果为是“0”。其“或”逻辑如表 9-3 所示。
表 9-3 “或”指令逻辑关系表
|
输入1
|
输入2
|
结果
|
|
0
|
0
|
0
|
|
0
|
1
|
1
|
|
1
|
0
|
1
|
|
1
|
1
|
1
|
【例 9.3】创建一个 POU,对变量 iVar1 和 iVar2 进行按位 “或”运算,并对这两个变量进行按位或运算,输出结果至 iResult,具体实现程序如图 9.4 所示。
VAR
iVar1:INT:=1;
iVar2:INT:=85;
iResult:INT;
END_VAR

图 9.4 按位或运算 CFC 程序图
程序的最终运行结果为 85。
-
布尔“或”OR
功能:布尔“或”运算指令用于计算两个布尔表达式的“或”结果。当两个布尔表达式中有一个表达式返回为真时,则结果为真;当两个布尔表达式的结果都是假时,则结果为假。
【例 9.4】创建一个 POU,利用布尔“或”运算,判断运算返回值,程序如图 9.5 所示。
VAR
iVar1: INT := 30;
bVar1: BOOL;
iResult: BOOL;
END_VAR

图 9.5 布尔或运算 CFC 程序图
由于 iVar1 的初始值为 30,故 iVar1<80 条件为真,而 bVar1 的初始值为“0”,故为假,一真一假最终的“或”逻辑结果可根据表 9-3 可以看出,为真。故等式右边的条件为真,程序的运行结果是 iResult 为 TRUE。
-
按位“非”NOT
功能:对逻辑串进行取反,将当前的值由“0”变“1”,或 由“1”变“0”。
按位“非”运算指令是将变量或常量逐一取非。其逻辑见表 9-4 所示。
表 9-4 “非”指令逻辑关系表
|
输入
|
结果
|
|
0
|
1
|
|
1
|
0
|
【例 9.5】创建一个 POU,利用按位“非”运算,判断运算返回值,程序如图 9.6 所示。
VAR
byVar1:BYTE:=1;
byVar2:BYTE;
END_VAR

图 9.6 按位非运算 CFC 程序图
由于 byVar1 的值为 1,将其转换为 2 进制后为 0000 0001,进行按位取反后,结果为 1111 1110。最终的输出结果为 254。
-
布尔“非”NOT
功能:布尔“非”运算指令用于计算单个布尔表达式的结果。当输入为真时,结果为假;当输入为假时,结果为真。
【例 9.6】创建一个 POU,利用布尔“非”运算,判断运算返回值,具体代码如下。
VAR
bResult:BOOL;
iVar1:INT:=30;
END_VAR

图 9.7 布尔非运算 CFC 程序图
由于 80<30 该命题为假,使用 NOT 指令对该布尔表达式取反后,得到的结果为真,故最后 byResult 的结果为 True。
-
按位“异或”XOR
功能:按位“异或”运算指令比较两个整数的相应位。
当两个整数的对应位是一个“1”而另外一个是“0”时,返回相应的结果位是“1”。当两个整数的相应位都是“1”或都是“0”时,则返回相应的结果位是“0”。
【例 9.7】创建一个 POU,对变量 iVar1 和 iVar2 进行按位“异或”运算,并输出结果,具体程序如图 9.8 所示。
VAR
iVar1:INT:=1;
iVar2:INT:=85;
iResult:INT;
END_VAR

图 9.8 布尔与运算 CFC 程序图
10 进制的 1 对应 2 进制数是 0000 0001,10 进制数 85 对应的 2 进制数是 0101 0101。根据按位“异或”运算指令的定义,其结果为 84。
按位异或位运算。只有当一个触点的输入状态为“1”,另一个触点的输入状态为“0”时,输出为“1”,如果两个触点状态同时为“1”或同时为“0”,则输出为“0”。其时序图如 9.9 所示。

图 9.9 基本逻辑指令时序图
【例 9.8】装修卧室时,通常都会选择安装双控开关面板。比如进卧室时在门口按开关 IX0.1 打开灯具,上床后不想起来,在床头也有一个开 IX0.2 控制卧室的灯 QX0.1,卧室门口的开关和床头的开关同时都可以独立的开关卧室的灯,请用位逻辑指令实现此功能。
程序如下,也可参考样例程序\第9章\01 BitLogic_XOR\。

图 9.10 异或指令使用举例
【例 9.9】某设备工作时有三台风机需要降温散热。当设备处于运行状态时,三台风机正常转动,则设备降温状态指示灯常亮;当其中任意两台风机转动时,则设备降温状态指示灯以 2Hz 的频率闪烁;当只有一台风机转动时,则设备降温状态指示灯以 0.5Hz 的频率闪烁;如三台风机都不转动时,则设备降温状态指示灯不亮。I/O 地址分配表见表 9-5。控制程序如图 9.11 所示。
表9-5 I/O地址分配表
|
地址
|
说明
|
地址
|
说明
|
|
%IX0.0
|
1号风机反馈信号
|
%IX0.0
|
设备降温状态指示灯
|
|
%IX0.1
|
2号风机反馈信号
|
%IX0.0
|
0.5Hz脉冲闪烁信号
|
|
%IX0.2
|
3号风机反馈信号
|
%IX0.1
|
2Hz脉冲闪烁信号
|
程序如下,请参考样例程序\第9章\\02 FanMonitor\。

图 9.11 风扇降温控制程序举例
-
布尔“异或”XOR
功能:布尔“异或”运算指令用于计算两个布尔表达式的结果,只有当其中一个表达式是真,另外一个表达式为假时,该表达式返回的结果才是真;当两个表达式的计算结果都是真或者都是假时,则返回的结果为假。
【例 9.10】创建一个 POU,利用布尔“异或”运算指令,判断返回值是 TRUE 还是 FALSE,具体程序如图 9.12 所示。
VAR
iVar1: INT := 30;
bVar1: BOOL;
iResult: BOOL;
END_VAR

图 9.12 布尔异或运算 CFC 程序图
程序的运行结果为 TRUE。
9.1.2 置位优先与复位优先触发器指令
在继电器系统中,一个继电器的若干对触点是同时动作的。在 PLC 中,指令是一条一条执行的,指令的执行是有先后次序的,没有“同时”执行的指令。
所以线圈格式的置位、复位指令有优先级。SR 触发器与 RS 触发器的置位输入和复位输入在同一条指令里,置位和复位输入谁在指令输入端的下面谁后执行。
SR 触发器为“置位优先”型触发器,当置位信号(SET1)和复位信号(RESET)同时为 1 时,触发器最终为置位状态; RS 触发器为“复位优先”型触发器,当置位信号(SET)和复位信号(RESET1)同时为 1 时,触发器最终为复位状态。置位优先 SR 与 RS 复位优先触发器指令参数如表 9-6 所示,指令表详见 9-7。
表9-6 置位优先SR与RS复位优先触发器指令
|
功能名
|
FB
|
ST
|
说明
|
|
置位优先SR与 RS复位优先触发器
|
![]() |
SR
|
置位优先触发器
|
![]() |
RS
|
复位优先触发器
|
表9-7 置位优先SR与RS复位触发器指令参数
|
名称
|
定义
|
数据类型
|
说明
|
|
SET1
|
输入变量
|
BOOL
|
置位优先命令
|
|
SET
|
输入变量
|
BOOL
|
置位命令
|
|
RESET1
|
输入变量
|
BOOL
|
复位优先命令
|
|
RESET
|
输入变量
|
BOOL
|
复位命令
|
|
Q1
|
输入变量
|
BOOL
|
输出
|
-
置位优先触发器 SR
功能:置位双稳态触发器,置位优先。逻辑关系:Q1=(NOT RESET AND Q1) OR SET1 其中 SET1 为置位信号,RESET 为复位信号。
语法:当 SET1 为“1”时,不论 RESET 是否为“1”,Q1 输出都为“1”;当 SET1 为“0” 时,如果 Q1 输出为“1”,一旦 RESET 为“1”,Q1 输出立刻复位为“0”。如果 Q1 输出为 “0”,不论 RESET 为“1”或者“0”,Q1 输出保持为“0”。其时序图详见图 9.13 的 a)所示,对应的状态表如图 9.13 的 b)所示。
![]() |
|
a)时序图 b) 状态表
图 9.13 SR 置位优先触发器时序图
【例 9.11】某系统需要一个停机信号,并要求系统出现故障后要求马上停机,控制设备停机的输出信号为 bStopMachine,如该变量被置位“1”,让需要让系统安全停机。否则可以正常运行。
|
表9-8 变量分配图
|
![]() |
图 9.14 SR 置位优先触发程序举例
设备的运行信号为 bRun,当系统中如出现任一故障 bError 会被置位“1”。具体变量分配表见表 9-8 所示,程序如图 9.14 所示,因为 bError 的优先权高于 bRun,故 bError 需要对应置位优先,只有当没有故障时,bRun 为 ON 才有意义。
-
复位优先触发器 RS
功能:复位双稳态触发器,复位优先。逻辑关系:Q1=NOT RESET1 AND (Q1 OR SET)其中 SET 为置位信号,RESET1 为复位信号。
语法:当 RESET1 为“1”时,不论 SET 是否为“1”,Q1 输出都为“0”;当 RESET1 为“0”时,如果 Q1 输出为“0”,一旦 SET 为“1”,Q1 输出立刻置位为“1”。如果 Q1 输出为“1”,不论 SET 为“1”或者“0”,Q1 输出保持为“1”。其时序图详见图 9.15 的 a)所示,对应的状态表如图 9.15 的 b)所示。
![]() |
|
-
时序图 b) 状态表
图 9.15 RS 复位优先触发器时序图
【例 9.12】控制电机正反转,旋转的方向通过按钮 S1 和 S2 来进行切换,当确认完方向后,按下 HALT 按钮,电机开始运转,请使用 RS 复位优先触发器来实现此功能。
方向选择按钮对应程序的状态为 S1 为电机顺时针运行方向,S2 为逆时针方向,程序声明及实现程序如下所示。
PROGRAM PLC_PRG
VAR_INPUT
S1 AT %IX0.1: BOOL;//电机顺时针按钮
S2 AT %IX0.2: BOOL;//电机逆时针按钮
HALT AT %IX0.0: BOOL;//电机 Halt 按钮
END_VAR
VAR
RS_1,RS_2: RS;//复位优先触发器
END_VAR
VAR_OUTPUT
K1 AT%QX0.0:BOOL;//顺时针执行
K2 AT%QX0.1:BOOL;//逆时针转行
END_VAR

图 9.16 RS 复位优先实现电机正反转控制
当选择完方向 S1 后,按下 HALT 按钮后,K1 接触器动作,反之,S2 按钮后,按下 HALT 按钮,K2 接触器动作,从而使电机进行顺时针运转,程序如图 9.16 所示。样例程序在\第 9 章\03 RS_MotorControl\中可以下载。
在实际的应用中,为了设备的安全及人员的安全,常常需要实现互锁功能,如旋转方向的控制按钮 S1 和 S2 就需要实现同一时间两者只能有一个为 ON,如果两个同时为 ON,则需要马上停机。为了实现上述功能,需要修改相应程序,其程序变量声明如例 9-12 一致,具体实现程序如图 9.17 所示。

图 9.17 带互锁功能的 RS 复位优先电机正反转控制
通过上述程序有效的实现了程序的互锁,一旦当 S1 和 S2 同时为 ON 后,马上停止输出,实现对设备及人员的保护。该样例程序在\第9章\04 RS_MotorControlWithInterLock\中可以查看。
9.1.3 边沿检测指令
边沿检测指令用来检测 BOOL 信号的上升沿(信号由 0---->1)和下降沿(信号由 1---->0)的变化,如图 9.18 所示。

图 9.18 边沿信号
在每个扫描周期中把信号状态和它在前一个扫描周期的状态进行比较,若不同则表明有一个跳变沿。因此,前一个周期里的信号状态必须被存储,以便能和新的信号状态相比较。 边沿检测指令表详见表 9-9,边沿检测指令参数如 图 9.18 边沿信号表 9-10 所示。
表9-9 边沿检测指令
|
功能块
|
图形化语言
|
文本话语言
|
说明
|
|
R_TRIG
|
![]() |
R_TRIG
|
上升沿检测
|
|
F_TRIG
|
![]() |
F_TRIG
|
下降沿检测
|
表9-10 边沿检测指令参数
|
名称
|
定义
|
数据类型
|
说明
|
|
CLK
|
报警信号源1
|
BOOL
|
被检测信号输入
|
|
Q
|
报警信号源2
|
BOOL
|
触发器状态输出
|
-
上升沿检测 R_TRIG
功能:用于检测上升沿。
语法:当 CLK 从“0”变为“1”时,该上升沿检测器开始启动,Q 输出先由“1”然后输出变为“0”,持续一个 PLC 运算周期;如果 CLK 持续保持为“1”或者“0”,Q 输出一直保持为“0”。
采集 bInput 信号的上升沿,程序如图 9.19 的 a)所示,其时序图如图 9.19 的 b)所示。详细程序可参考样例程序\第9章\05 R_TRIG\。
![]() |
![]() |
图 9.19 上升沿触发程序
a ) 上升沿触发程序 b ) 上升沿触发时序图
【例 9.13】工业项目中,常会使用到报警显示,使用上升沿触发指令检测报警信号源,通过置位复位功能控制报警显示,变量分配表见表 9-11 所示,程序如图 9.20 所示,也可参考样例程序\第9章\06 AlarmTrig\。
表9-11 变量分配表
|
变量名
|
说明
|
变量名
|
说明
|
|
bAlarm1
|
报警信号源1
|
bAlarm4
|
报警信号源4
|
|
bAlarm2
|
报警信号源2
|
bReset
|
复位按钮
|
|
bAlarm3
|
报警信号源3
|
bTowerLightRed
|
报警红色显示灯
|
程序变量声明如下,
PROGRAM PLC_PRG
VAR
RS_0:RS;
bAlarm1,bAlarm2,bAlarm3,bAlarm4:BOOL;
R_TRIG_0:R_TRIG;
R_TRIG_1: R_TRIG;
bReset:BOOL;
bTowerLightRed:BOOL;
END_VAR

图 9.20 报警显示复位 CFC 程序举例
-
下降沿检测 F_TRIG
功能:用于检测下降沿。
语法:当 CLK 从“1”变为“0”时,该下降沿检测器开始启动,Q 输出先由“1”然后输出变为“0”,持续一个 PLC 运算周期;如果 CLK 持续保持为“1”或者“0”,Q 输出一直保持为“0”。
【例 9.14】采集 bInput 信号的下降沿,当 bInput 由 True 变为 False 时,功能块 F_TRIG.Q 会根据下降沿的触发事件给出相应输出,输出时间维持在一个周期。程序如图 9.21 所示,可参考样例程序\第9章\07 F_TRIG\。


a ) 下降沿触发程序 b ) 下降沿触发时序图
图 9.21 上升沿触发程序
9.2 定时器指令
9.2.1 定时器
定时器采用 IEC61131-3 标准的定时器,分为脉冲定时器 TP、通电延时定时器 TON、断电延时定时器 TOF 和实时时钟 RTC。所有定时器指令的图形化与文本化指令表如表 9-12 所示,定时器指令参数表详见 9-13。
表9-12定时器指令的图形化与文本化指令表
|
定时器指令
|
图形化语言
|
文本化语言
|
说明
|
|
定时器
|
![]() |
TP
|
脉冲定时器
|
![]() |
TON
|
通电延时定时器
|
|
![]() |
TOF
|
断电延时定时器
|
|
![]() |
RTC
|
实时时钟
|
表9-13 定时器指令参数
|
名称
|
定义
|
数据类型
|
说明
|
|
IN
|
输入变量
|
BOOL
|
启动输入
|
|
PT
|
输入变量
|
TIME
|
延时时间
|
|
Q
|
输入变量
|
BOOL
|
定时器输出
|
|
ET
|
输入变量
|
TIME
|
当前定时时间
|
定时器时序图详见图 9.22 所示。

图 9.22 定时器特性时序图
-
脉冲定时器 TP
功能:脉冲定时。
语法:在定时器的输入端 IN 从“0”变为“1”时,定时器则启动,无论定时器输入端 IN 如何变化,定时器的实际运行时间都是用户所定义的 PT 时间,在定时器运行时,其输出端 Q 的输出信号为“1”。
输出端 ET 为输出端 Q 提供定时时间。定时从 T#0s 开始,到设置的 PT 时间结束。当 PT 时间到时,ET 会保持定时时间直到 IN 变为“0”时。如果在达到 PT 定时时间之前输入 IN 已经变成“0”,输入 ET 编程 T#0s,PT 定时的时刻。为了复位该定时器,只需要设置 PT=T#0s 即可。
【例 9.15】使用脉冲定时器 TP 制作一个指示灯闪烁程序,ON 维持时间为 1s,OFF 维持时间为五秒。
程序中使用两个TP定时器,控制定时器ON维持1s的输入通过OFF定时器的输出信号取反作为控制。变量分配表见表 9-14 所示,程序如图 9.23 所示,也可以参考样例程序\第9章\08 Sample_TP\。
表 9-14 变量分配表
|
变量名
|
说明
|
|
bTowerLightGreen
|
指示灯输出
|
图 9.23 TP定时器程序

-
通电延时定时器 TON
功能:通电延时定时。
在定时器的输入端 IN 从“0”变为“1”时,定时器则启动,当到达定时时间 PT 且输入端的信号 IN 始终维持在“1”时,其输出端 Q 的输出信号为“1”,如果在定时器的定时时间到达之前,输入端 IN 信号由“1”变为“0”时,则定时器复位,下一个 IN 信号的上升沿定时器重启。
输出端 ET 提供定时时间,延时从 T#0s 开始,到设置的 PT 时间结束。PT 到达时,ET 将会保持定时时间直到 IN 变为“0”为止。如果在达到 PT 定时时间之前,输入 IN 变为“0”,输出 ET 立即变为 T#0s。为了重启定时器,可以设置 PT=T#0s,也可以将 IN=FALSE。
【例 9.16】两台电动机 M1、M2,要求当启动时按下启动按钮 DI_bStart 后,M1 启动,20 秒后 M2 启动;当需要停车时按下停止按钮 DI_bStop,M2 停车,10 秒后 M1 停车。每台电动机都有过载保护,当任一台电动机过载时,两台电动机同时停车。变量分配表见表 9-15 所示。
表9-15 变量分配表
|
DI_bStop
|
停止按钮
|
|
DI_bFuse1
|
M1过载保护
|
|
DI_bFuse2
|
M2过载保护
|
|
DO_KM_M1
|
启动M1
|
|
DO_KM_M2
|
启动M2
|
当按下启动按钮 DI_bStart 时,马上置 DO_KM_M1 为“1”,并通过自锁信号触发 M2 电机启动延时,达到 20s 后,定时器 M2_StartDelay.Q 被置位“1”,通过此信号启动 M2 电机。
当需要停止时,按下停止按钮 DI_bStop 后,置中间变量 bStopTemp 为“1”,且马上停止 M2 电机,并通过该中间变量启动 M1 电机的停止延时定时器 M1_StopDelay,到达设定时间 10s 后,M1 也停止。程序如图9.23 所示,也可参考样例程序\第9章\09 MotorStartStopDelay\。

图 9.23 电机延时启动程序举例
-
断电延时定时器 TOF
功能:断电延时定时。
在定时器的输入端 IN 从“1”变为“0”时,定时器的 Q 输出信号为“1”,定时器的启动输入端变为“0”时,定时器则启动,只要当定时器在运行,其输出 Q 一直为“1”,当到达定时时间时,输出端 Q 复位,在到达定时时间之前,如果定时器的输入端返回为“1”,则定时器复位,输出端的 Q 输出信号保持为“1”。可参考图 6.x 中的 TOF 相关时序图。
输出端 ET 提供定时时间,延时从 T#0s 开始到设置的定时时间 PT 结束。当 PT 时间到时,ET 将保持定时时间直到输入 IN 返回“1”为止。如果在达到 PT 定时时间之前,输入 IN 变为“1”,输出 ET 立即变为 T#0s。为了复位定时器,可以设置将 PT=T#0s。
【例 9.17】在车内灯光控制中,打开车门时,车内灯会点亮,即使关上车门 10 秒钟内,车内的灯还会继续亮着,此种控制用的就是定时器断开延时动作模式。如下通过 PLC 程序实现此功能。 程序时序图如图 9.24 所示,当车门打开时,bDI_Door 门锁信号为“1”,关闭时为“0”。程序如图 9.25 所示,变量分配表见表 9-16 所示。样例程序\第9章\10 TOF_CarIndoorLight\。

图 9.23 汽车车内等控制程序时序图
表 9-16 变量分配表
|
变量名
|
说明
|
|
bDI_Door
|
车门门锁信号
|
|
bDO_IndoorLight
|
车内灯
|
图 9.25 TOF车门定时器程序

-
实时时钟 RTC
功能:在给定时间启动,返回当前日期和时间。
语法:RTC(EN, PDT, Q, CDT) 表示:当 EN 为 “0”,输出变量 Q 以及 CDT 为 “0”相关时间为 DT#1970-01-01-00:00:00。一旦 EN 为“1”,PDT 给予的时间将会被设置,并且将会以秒进行计数一旦 EN 为 TRUE 将返回 CDT 。一旦 EN 被复位为 FALSE, CDT 将会被复位为初始值 DT#1970-01-01-00:00:00。请注意,PDT 时间只上升沿有效。RTC 定时器参数表详见 9-17 所示。
表9-17 标准定时器指令参数
|
名称
|
定义
|
数据类型
|
说明
|
|
EN
|
输入变量
|
BOOL
|
启动使能
|
|
PDT
|
输入变量
|
DATE_AND_TIME
|
设置将要启动的时间和日期
|
|
Q
|
输入变量
|
BOOL
|
状态输出
|
|
CDT
|
输入变量
|
DATE_AND_TIME
|
当前计数时间和日期的状态
|
【例 9.18】创建一个 POU,使用 RTC 指令,为其设定初始时间,并当 bEnable 变量 ON 后,返回 ON 后的当前日期和时间。

图 9.26 RTC 指令应用举例
程序如图 9.26 所示,样例程序可参考\第9章\11 RTC_Timer\。
9.3 计数器指令
9.3.1 计数器简介
MetaFacture 标准功能库中提供了加、减计数功能块,系统提供了 CTU 加计数器、CTD 减计数器和 CTUD 加减计数器三个功能块。
9.3.2 计数器指令
标准库中自带所有计数器指令的图形化与文本化指令表如表 9-18 所示,计数器指令参数表详见 9-19。
表 9-18 标准计数器的图形化与文本化指令表
|
计数器指令
|
图形化语言
|
文本化语言
|
说明
|
|
计数器
|
![]() |
CTU
|
增计数器
|
![]() |
CTD
|
减计数器
|
|
![]() |
CTUD
|
增/减计数器
|
表9-19 标准计数器指令参数
|
名称
|
定义
|
数据类型
|
说明
|
|
CU
|
输入变量
|
BOOL
|
检测上升沿的信号输入触发输出CV递增
|
|
CD
|
输入变量
|
BOOL
|
检测上升沿的信号输入触发输出CV递增
|
|
RESET
|
输入变量
|
BOOL
|
复位计数器
|
|
LOAD
|
输入变量
|
BOOL
|
加载计数器
|
|
Q
|
输出变量
|
BOOL
|
CV递增到计数上限PV时,输出TRUE
|
|
QU
|
输出变量
|
BOOL
|
CV递增到计数上限PV时,则QU输出TRUE
|
|
QD
|
输出变量
|
BOOL
|
输出CV递减到0时,则QD输出TRUE
|
|
CV
|
输出变量
|
WORD
|
当前计数值
|
-
增计数器 CTU
当计数器输入端 CU 的信号从状态“0”变为状态“1”时,当前计算值加 1,并通过输出端CV 进行显示,第一次调用时(复位输入 RESET 信号状态为“0”),输入 PV 端的计数为默认值,当计数达到上限 32767 后,计数器将不会再增加,CU 也不会再起作用。
当复位输入端 RESET 的信号状态为“1”时,计数器的 CV 和 Q 都为“0”,只要输入端RESET 状态为“1”,上升沿对 CU 就不再起作用。当 CV 值大于或等于 PV 时,输出端 Q 为“1”。此时 CV 仍可继续累加,输出端 Q 继续为输出“1” 。
增计数器 CTU 指令示例如图 9.27 所示,时序图如 9.28 所示。

图 9.27 增计数器 CTU 使用举例

图 9.28 增计数器 CTU 特性时序图
增量功能块。输入变量 CU 和复位 RESET 以及输出变量 Q 是布尔类型的,输入变量 PV 和输出变量 CV 是 WORD 类型。
CV 将被初始化为 0 ,如果复位 RESET 是 TRU 真的。如果 CU 有一个上升沿从 FALSE 为TRUE ,CV 提升 1,Q 将返回 TRUE,如此 CV 将大于或等于上限 PV。
【例 9.18】某工厂要实现每天的产量计数,每个产品出厂前都会经过流水线,流水线上有一个光电传感器,当产品经过时,该信号会被置为“1”,示意图如图 9.29 的 a)所示。通过计数器指令,使用程序计算输出的总产量。
![]() |
![]() |
图 9.29 增计数器 CTU 使用举例
a) 应用示意图 b)程序梯形图
分配表请见表 9-20,当流水线上有产品流经时, bDI_ConverySensor 的感应状态对应为“1”,无产品时为 “0”,故可直接使用此信号作为增计数器 CTU 的 CU 输入信号,当前实时值通过 nCurrentValue 进行显示。bDI_Reset 作为清零信号清除当前值。样例程序请参考\第 9 章\12 Counter_Convery\。
表9-20 变量分配表变量
|
变量名
|
说明
|
|
bDI_ConverSensor
|
传输带传感器信号
|
|
bDI_Reset
|
计数器复位按钮
|
|
nCurrentValue
|
当前产品总数
|
-
减计数器 CTD
当减计数器输入端的 CD 信号从“0”变为状态“1”时,当前计数值减 1,并在输出端上 CV 显示当前值,第一次调用时(需要将加载输入端信号 LOAD 初始化,需要将其从“0”变为状态 “1”,再变为状态“0”后功能块才能生效),输入 PV 端的计数为默认值,当计数达到 0 后,计数值将不在会减少,CD 也不再起作用。
当加载输入端信号 LOAD 为“1”时,计数值将设定成 PV 默认值,只要加载输入端信号 LOAD 状态为“1”,输入端的 CD 上升沿就不起作用。当 CV 值小于或等于 0 时,输出端 Q 为“1”。减计数器 CTD 指令示例如图 9.30 所示,时序图如 9.31 所示。

图 9.30 减计数器 CTD 使用举例

图 9.31 减计数器 CTD 特性时序图
【例 9.19】某工厂生产的产品每 25 个可以装一箱,流经流水线后,每次满箱后,需要输出一个 3s 的延时指示 bPackingDone 信号,流水线上装有光电传感器,通过 bDI_ConverySensor 信号反馈给 PLC。此外需要统计当日生产的总箱数 nPackageQTY。

图 9.32 减计数器 CTU 程序举例
变量分配表如表 9-21 所示,使用传输线上的 bDI_ConverySensor 传感器信号作为 CTD 功能块的 CD 源信号,PV 给定 25,当满 25 箱时 Counter_Down.Q 输出一个高电平脉冲作为满箱的 BOOL 信号。同时将此信号作为累计箱数的 Package_Counter 计数器的 CU 源信号,
nPackageQTY 为当日的生产总箱数。满箱指示灯通过使用 TP 功能块做延时输出。程序如图 9.32 所示。样例程序请参考\第9章\13 CTD_Packing\。
表 9-21 变量分配表
|
变量名
|
说明
|
|
bDI_ConverSensor
|
传输带传感器信号
|
|
bPackingDone
|
m满箱指示灯
|
|
nPackageQTY
|
当日生产总箱数
|
-
增/减双向计数器 CTUD
当加计数输入端的 CU 信号从“0”变为状态“1”时,当前计数值加 1,并在输出 CV 上显示。当减计数输入端的 CD 的信号状态从“0”变为状态“1”时,当前计数值减 1,并在输出端 CV 上显示。如果两个输入端都是上升沿,当前计数值将保持不变。
当计数值达到上限值 32767 后,加计数输入端 CU 的上升沿不再起作用。因此即使加计数输入端 CU 出现上升沿,及数值也不会增加。同理,当计数值达到下极限值 0 后,减计数输入端 CD 也不会在其作用,因此,即使减计数输入端 CD 出现上升沿,计数值也不会减少。
当 CV 值大于或等于 PV 值时,输出 QU 为“1”。当 CV 值小于或等于 0 时,输出 QD 为“1”。
【例 9.20】创建一个 POU,使用增/减双向计数器 CTUD,当 bUp 有上升沿信号时,计数值增加, bDown 有上升沿信号时,计数值减小。bReset 用于数据复位,具体代码如下,程序如图 9.33 所示。
VAR
CTUD_0: CTUD;
bUp: BOOL;
bDown: BOOL;
bRest: BOOL;
bLoad: BOOL;
xx: INT;
ss: BOOL;
zz: INT;
END_VAR

图 9.33 增/减计数器 CTUD 使用举例
【例 9.21】一自动仓库存放某种货物,最多 6000 箱,需对所存的货物进出计数,货物多于 1000 箱,灯 L1 亮;货物多余 5000 箱,灯 L2 亮。进货的输入信号为 bInput,出货对应输入信号为bOutput。具体详见表 9-22 的变量分配表。
表 9-22 变量分配表
|
变量名
|
说明
|
|
bInput
|
进货
|
|
bOutput
|
出货
|
|
nL1Value
|
数值1000
|
|
nL2Value
|
数值5000
|
|
L1
|
多于1000指示灯
|
|
L2
|
多于5000指示灯
|

图 9.34 自动仓库进出货计数功能举例
9.4 数据处理指令
MetaFacture 标准功能库中所提供数据处理指令包括选择操作指令、比较指令和移位指令等,下文会对各部分的指令进行详细说明。
9.4.1 选择操作指令
在实际的应用中常会用到一些数据的选择和筛选,在选择操作指令中会介绍几种常用的指令供读者在将来的实际应用中提供便利,常用选择操作指令如表 9-23 所示。
表 9-23 选择操作指令的图形化与文本化指令表
|
选择操作指令
|
图形化语言
|
文本化语言
|
说明
|
|
选择操作指令
|
![]() |
SEL
|
二选一指令
|
![]() |
MAX
|
取最大值
|
|
![]() |
MIN
|
取最小值
|
|
![]() |
LIMIT
|
限制值
|
|
![]() |
MUX
|
多选一
|
-
二选一指令 SEL
功能:通过选择开关,在两个输入数据中选择一个作为输出,选择开关为 FALSE 时,输出为第一个输入数据,选择开关为 TRUE 时,输出为第二个数据。
语法:其文本化语言语法格式如下,
OUT := SEL(G, IN0, IN1)
参数 G 必须是布尔变量。如果 G 是 FALSE,则返回值的结果是 IN0, 如果 G 是 TRUE ,则返回值的结果为 IN1,其参数说明详见表 9-24 所示。
表9-24二选一指令 SEL 参数说明
|
名称
|
定义
|
数据类型
|
说明
|
|
G
|
输入变量
|
BOOL
|
输入选择位
|
|
IN0
|
输入变量
|
任何类型
|
输入数据0
|
|
IN1
|
输入变量
|
任何类型
|
输入数据1
|
|
返回值
|
输出变量
|
任何类型
|
输出数据
|
【例 9.22】创建一个 POU,当输入值 bInput 为 FALSE,输出为 3,反之,当其为 TRUE 时,输出为 4,具体实现程序如下。
VAR
iVar1:INT:=3;
iVar2:INT:=4;
iOutVar: INT;
bInput: BOOL;
END_VAR
iOutVar:=SEL(bInput,iVar1,iVar2);
-
取最大值 MAX
功能:最大值函数。在多个输入数据中选择最大值作为输出。
语法:其文本化语言语法格式如下所示,
OUT := MAX(IN0, …,INn)
其参数说明详见表 9-25 所示。
表9-25 取最大值 MAX 参数说明
|
名称
|
定义
|
数据类型
|
说明
|
|
IN0
|
输入变量
|
任何类型
|
输入数据0
|
|
INn
|
输入变量
|
任何类型
|
输入数据n
|
|
返回值
|
输出变量
|
任何类型
|
输出数据
|
【例 9.23】创建一个 POU,iOutVar 的输入值为 iVar1 和 iVar2 中的较大者,具体实现程序如下。
VAR
iVar1:INT:=30; iVar2:INT:=60;
iOutVar: INT;
END_VAR
iOutVar:=MAX(iVar1,iVar2);
程序运行后输出结果为 60。
-
取最小值 MIN
功能:最小值函数。在多个输入数据中选择最小值作为输出。
语法:其文本化语言语法格式如下所示,
OUT := MIN(IN0, …,INn)
IN0, INn 以及 OUT 可以是任何数据类型,其参数说明详见表 9-26 所示。
表9-26取最小值 MIN 参数说明
|
名称
|
定义
|
数据类型
|
说明
|
|
IN0
|
输入变量
|
任何类型
|
输入数据0
|
|
INn
|
输入变量
|
任何类型
|
输入数据n
|
|
返回值
|
输出变量
|
任何类型
|
输出数据
|
【例 9.24】创建一个 POU,iOutVar 的输入值为 iVar1 和 iVar2 中的较小者,具体实现程序如下。
VAR
iVar1:INT:=30; iVar2:INT:=60;
iOutVar: INT;
END_VAR
iOutVar:=MIN(iVar1,iVar2);
程序运行后输出结果为 30。
-
多选一 MUX
功能:多路器操作。通过控制数在多个输入数据中选择一个作为输出。
语法:其文本化语言语法格式如下,
OUT := MUX(K, IN0,...,INn)
IN0,...,INn 以及 返回值可以是任何变量类型。但是 K 必须为 BYTE, WORD, DWORD, LWORD, SINT, USINT, INT, UINT, DINT, LINT, ULINT 或者 UDINT。 MUX 从变量组中选择第 K 个数据输出。其参数说明详见表 9-27 所示。
表9-27 多选一 MUX 参数说明
|
名称
|
定义
|
数据类型
|
说明
|
|
IN0
|
输入变量
|
任何类型
|
输入数据0
|
|
INn
|
输入变量
|
任何类型
|
输入数据n
|
|
返回值
|
输出变量
|
任何类型
|
输出数据
|
|
K
|
输入变量
|
整数类型
|
控制数
|
【例 9.25】创建一个 POU,使用多选一指令,根据输入控制数 iVar 选择最终要输出的数据。
具体实现程序如下。
VAR
iVar:INT:=1;
iOutVar: INT;
END_VAR
iOutVar:=MUX(iVar,30,40,50,60,70,80);
最终输出结果为 40,因为数据排序是从第 0 个元素开始累积。
如果数据超出范围,最终数据按最后一个数据为输出,如例 6.x 中,将 iVar 的值设定为 10,最终的输出结果为 80。如果 iVar 为-1,最终输出值还是为 80。
-
限制值 LIMIT
功能:限制值输出。判断输入数据是否在最小值和最大值之间,若输入数据在两者之间,则直接把输入数据作为输出数据进行输出。若输入数据大于最大值,则把最大值作为输出值。若输入数据小于最小值,则把最小值作为输出值。
语法:其文本化语言语法格式如下,
OUT := LIMIT(Min, IN, Max)
IN, Min ,Max 以及返回值可以是任何数据类型,其参数说明详见表 9-28 所示。
表9-28限制值 LIMIT 参数说明
|
名称
|
定义
|
数据类型
|
说明
|
|
Min
|
输入变量
|
任何类型
|
输入数据0
|
|
IN
|
输入变量
|
任何类型
|
输入数据n
|
|
返回值
|
输出变量
|
任何类型
|
输出数据
|
|
Max
|
输入变量
|
任何类型
|
输入数据n
|
【例 9.26】创建一个 POU,使用限制值指令,无论输入为何值,确保输出值在能在 30~80 的范围内。具体实现程序如下。
VAR
iVar:INT:=90; iOutVar: INT;
END_VAR
iOutVar:=limit(30,iVar,80);
最小值输入值为 30,最大值输入值为 80,实际输入值为 90,大于最大值,故最终输出以最大值 80 为输出,故最终结果为 80。
9.4.2 比较指令
比较指令用于两个相同数据类型的有符号数或无符号数 IN1 和 IN2 的比较判断操作。涉及到的运算有: = ,>=,<=,>,<,<>在图形化语言中,比较指令是以动合触点的形式编程的,在动合触点的中间注明比较参数和比较运算符。当比较的结果为真时,该动合触点闭合;在文本化语言中,比较指令可以用符号直接表示,当比较结果为真时, PLC 将运算结果置 True。比较指令的图形化及文本化指令的表现形式见表 9-29。
表9-29 比较指令的图形化及文本化指令表
|
比较指令
|
图形化语言
|
文本化语言
|
说明
|
|
比较指令
|
![]() |
=
|
相等
|
![]() |
<>
|
不等
|
|
![]() |
>
|
大于
|
|
![]() |
>=
|
大于等于
|
|
![]() |
<
|
小于
|
|
![]() |
<=
|
小于等于
|
-
大于
功能:当第一个操作数大于第二个操作数,布尔运算符返回值是 TRUE。该个操作数类型 BOOL,BYTE,WORD,DWORD,SINT,USINT,INT,UINT,DINT,UDINT,REAL,LREAL,TIME,DATE,TIME_OF_DAY,DATE_AND_TIME 和 STRING。
语法:其文本化语言语法格式如下,
bResult := bVar1 >bVar2;
【例 9.27】由于 INT 类型的变量他的数值有效范围为-32768~32767,该类型存在正负,在实际的应用中常常需要判断其符号。如果数值为负数,该变量的最高位为 1,如可以使用 32766 作为界定线,一旦当前的数值大于 32766,既可以判断当前的数值为负值,从而进行下一步动作。该判断程序的声明部分如下所示,具体程序如图 9.35 所示。
PROGRAM PLC_PRG
VAR_INPUT
nValue:INT;//输入值
END_VAR VAR_OUTPUT
bOverFlow AT%QX0.0: BOOL;//符号位溢出
END_VAR

图 9.35 大于函数 CFC 程序应用举例
当 nValue 的数值大于 32766 时,bOverFlow 会被置为 TRUE,故可通过该位来判断当前数值是正值还是负值。详细程序可以参考\第9章\15 GreatThan\中的样例程序。
-
大于等于
功能:当第一个操作数大于或等于第二个操作数,布尔运算符返回值是 TRUE。该个操作数类型 BOOL,BYTE,WORD,DWORD,SINT,USINT,INT,UINT,DINT,UDINT,REAL,
LREAL,TIME,DATE,TIME_OF_DAY,DATE_AND_TIME 和 STRING。语法:其文本化语言语法格式如下,
bResult := bVar1 >=bVar2;
【例 9.28】由于 UINT 类型的变量他的数值有效范围为 0~65535,如果数值大于该范围,则会有溢出,为了防止此现象,在程序中可以做一个溢出警告,当数值大于等于 65530 时,即给出警告信息提醒将数据清零。该判断程序的声明部分如下所示,具体程序如图 9.36 所示。
PROGRAM PLC_PRG VAR_INPUT
nValue:UINT;//输入值
END_VAR
VAR_OUTPUT
bOverFlow AT%QX0.0: BOOL;//溢出警告
END_VAR

图 9.36 大于等于函数 CFC 程序应用举例
当 nValue 的数值大于等于 65530 时,bOverFlow 会被置为 TRUE,详细程序可以参考\第5 章\16 GreatEqual\中的样例程序。
-
等于
功能:当第一个操作数等于第二个操作数,布尔运算符返回值是 TRUE。该个操作数类型BOOL,BYTE,WORD,DWORD,SINT,USINT,INT,UINT,DINT,UDINT,REAL,LREAL,TIME,DATE,TIME_OF_DAY,DATE_AND_TIME 和 STRING。语法:其文本化语言语法格式如下,
bResult := bVar1 =bVar2;
【例 9.29】判断 S1 按钮和 S2 的按钮,如果两个按钮状态相同时,则 K1 输出为 ON,反之为 FALSE。该判断程序的声明部分如下所示,具体程序如图 9.37 所示。
PROGRAM PLC_PRG
VAR_INPUT
S1 AT%IX0.0:BOOL;//输入按钮 1
S2 AT%IX0.1:BOOL;//输入按钮 2
END_VAR
VAR_OUTPUT
K1 AT%QX0.0:BOOL;//输出指示灯
END_VAR

图 9.37 等于函数 CFC 程序应用举例
按钮 S1 与 S2 为两个输入按钮,当两个同时为 ON 或者同时为 OFF 时,K1 则有输出 ON 信号详细程序可以参考\第9章\17 Equal\中的样例程序。
-
小于
功能:当第一个操作数小于第二个操作数,布尔运算符返回值是 TRUE。该个操作数类型BOOL,BYTE,WORD,DWORD,SINT,USINT,INT,UINT,DINT,UDINT,REAL,LREAL,TIME,DATE,TIME_OF_DAY,DATE_AND_TIME 和 STRING。语法:其文本化语言语法格式如下,
bResult := bVar1 <bVar2;
【例 9.30】如果当输入数值 nVar1 小于输入数值 nVar2 时,则 K1 有输出。该判断程序的声明部分如下所示,具体程序如图 9.38 所示。
PROGRAM PLC_PRG VAR_INPUT nVar1 :WORD;//输入数值 1 nVar2 :WORD;//输入数值 2
END_VAR
VAR_OUTPUT
K1 AT%QX0.0:BOOL;//输出指示
END_VAR

图 9.38 小于函数 CFC 程序应用举例
详细程序可以参考\第9章\18 LessThan\中的样例程序。
-
小于等于
功能:当第一个操作数小于或等于第二个操作数,布尔运算符返回值是 TRUE。该个操作数类型 BOOL,BYTE,WORD,DWORD,SINT,USINT,INT,UINT,DINT,UDINT,REAL,LREAL,TIME,DATE,TIME_OF_DAY,DATE_AND_TIME 和 STRING。语法:其文本化语言语法格式如下,
bResult := bVar1 <= bVar2;
【例 9.31】byVar1 为 WORD 类型变量,如当其实际值超过 255 时,程序输出警告 K1,该判断程序的声明部分如下所示,具体程序如图 9.39 所示。
PROGRAM PLC_PRG
VAR_INPUT
byVar1 :WORD;//输入数值 1
END_VAR
VAR_OUTPUT
K1 AT%QX0.0:BOOL;//输出指示
END_VAR

图 9.39 小于等于函数 CFC 程序应用举例
详细程序可以参考\第9章\19 LessEqual\中的样例程序。
-
不等于
功能:当第一个操作数不等于第二个操作数,布尔运算符返回值是 TRUE。该个操作数类型BOOL,BYTE,WORD,DWORD,SINT,USINT,INT,UINT,DINT,UDINT,REAL,LREAL,TIME,DATE,TIME_OF_DAY,DATE_AND_TIME 和 STRING。语法:其文本化语言语法格式如下,
bResult := bVar1<> bVar2;
【例 9.32】tTime 为事件类型变量,将其与固定数值 1 小时 20 分钟 10 秒进行比较,如果当前数值 tTime 不等于该固定时间时,程序输出运行信号 K1,该判断程序的声明部分如下所示,具体程序如图 9.40 所示。
PROGRAM PLC_PRG
VAR_INPUT tTime :TIME;//输入时间数值 1
END_VAR
VAR_OUTPUT
K1 AT%QX0.0:BOOL;//输出指示
END_VAR

图 9.40 不等于函数 CFC 程序应用举例
详细程序可以参考\第9章\20 UnEqual\中的样例程序。
【例 9.33】某风力发电设备需要对发电机温度进行实时监控,要求程序能够当发电机温度大于等于 90 摄氏度,并且时间维持在 1min 以上,发出发电机过热警告;当温度小于等于 60 摄氏度,且时间维持在 1min 以上,发出发电机温度过低警告。变量分配表如表 9-30 所示。
程序通过 GE 与 LE 指令对输入温度 AI_rGenTemperature 进行比较。输出结果直接赋值给定时器的输入端 IN。程序如图 9.41 所示,样例程序请参考\第9章\21 Temp_CMP\。
表9-30 变量分配表
|
变量名
|
说明
|
|
AI_rGenTemperaturer
|
发电机温度
|
|
bTempHighAlarm
|
温度过高报警
|
|
bTempLowAlarm
|
温度过低报警
|

图 9.41 发电机温度报警程序举例
9.4.3 移位指令
移位操作指令是 MetaFacture 中经常使用的指令,它分为按位移位指令,循环移位指令两大类。其功能为将操作数的所有位按操作指令规定的方式移动 1 位 n 次移动,将其结果送入返回值。移位指令表的图形化及文本化指令表详见表 9-31 所示。
表9-31 移位指令的图形化及文本化指令表
|
比较指令
|
图形化语言
|
文本化语言
|
说明
|
|
比较指令
|
![]() |
SHL
|
按位左移
|
![]() |
SHR
|
按位右移
|
|
![]() |
ROL
|
循环左移
|
|
![]() |
ROR
|
循环右移
|
-
按位左移 SHL
功能:对操作数进行按位左移,左边移出位不做处理,右边空位自动补 0。
语法:指令可以将输入 IN 中的数据左移 n 位,输出结果赋值至 OUT,二进制数左移一位相当于将原数乘以 2。如果 n 大于数据类型宽度,BYTE, Word 和 DWORD 值将填补为零。文本化语言语法格式如下所示,
OUT:= SHL (IN, n)
【例 9.34】利用了按位左移指令完成 WORD 类型输入变量 wWord1 当前值左移 4 位,程序如9.42 所示,样例程序请参考\第9章\22 SHL\。

图 9.42 按位左移程序举例

图 9.43 按位左移 4 位过程
wWord1 为 十进制的1,即16 进制的 0001,经过按位向左移动 4 位后,最终输出结果为十进制的16,也是十六进制的16#0010。其过程见图9.43。低 4 位的空位补 0。
移位运算的总位数会受到输入变量的数据类型的影响。如果输入变量是常量,将会取长度最小的数据类型。而输出变量的数据类型则不会对算术运算产生影响,通过如下例子鉴别两者的区别。
【例 9.35】请比较下面 16 进制数的按位左移的运算,尽管 byte 和 word 形式的输入变量值相等,但根据输入变量的数据类型不同(BYTE 或 WORD),erg_byte 和 erg_word 将得到不同的结果。
VAR
in_byte : BYTE:=16#45;
in_word : WORD:=16#45;
erg_byte : BYTE;
erg_word : WORD;
n: BYTE :=2;
END_VAR
erg_byte:=SHL(in_byte,n); (* 结果为 20 *)
erg_word:=SHL(in_word,n); (* 结果为276 *)

图 9.44 BYTE 与 WORD 变量按位左移比较
当 BYTE 类型变量 b6 和 b7 位左移 2 位后溢出,最终的数据为 十 进制的 20。而当 WORD 类型变量的 b6 和 b7 位左移两位后,进入高字节的 b8 和 b9 位,该位会继续保留,最终的结果为 十 进制的 276。其过程见图 9.44 所示。
-
按位右移 SHR
功能:对操作数进行按位右移,右边移出位不做处理,左边空位自动补 0。
语法:指令可以将输入 IN 中的数据右移 n 位,输出结果赋值至 OUT,二进制数右移一位相当于将原数除以 2。如果 n 大于数据类型宽度, BYTE, Word 和 DWORD 值将填为零。如果使用带符号数据类型,则算术移位将按最高位补充数。其文本化语言语法格式如下所示,
OUT:= SHR (IN, n)
【例 9.36】利用按位右移指令完成 WORD 类型输入变量 wWord1 的当前值右移 5 位,输出结果赋值给 wWord2,程序如 9.45 所示,样例程序请参考\第9章\23 SHR_WORD\。

图 9.45 按位右移程序举例

图 9.46 按位右移 5 位过程
如上,wWord1 为十进制的256, 即16 进制的 0100,经过向右移动 5 位后,最终输出结果为十进制的8。由于 WORD 类型变量属于无符号数据类型,有效值从 0~65535,故右移 5 位后,没有符号位,高 5 位补 0,移位过程如图 9.46 所示。
例 9.36 为无符号位的数据右移,如遇到有符号整型数据,高位右移需要补符号位。如下例9.37 所示。
【例 9.37】利用按位右移指令完成 INT 类型输入变量 iINT1 的当前值右移 4 位,输出结果赋值给 iINT2,程序如 9.47 所示,样例程序请参考\第9章\24 SHR_INT\。

图 9.47 带符号位的按位右移程序举例

图 9.48 带符号位的按位右移 4 位过程
如上,由于 INT 为有符号位数据,有效值为-32768~32767,iINT1 为十进制的-3840,即 16 进制有符号数据 F100,最高位 b15 为符号位,经过向右移动 4 位后,需要补数据,由于源数据符号位为 1,故高 4 位补 4 个 1,故程序运行最终结果为 十进制的-240,具体移位过程如图 9.48 所示。
-
循环左移 ROL
功能:对操作数进行按位循环左移,左边移出的位直接补充到右边的最低位。
语法:允许的数据类型:BYTE、WORD、DWORD,使用该指令可以将输入 IN 中的全部内容循环的逐位左移,空出的位用移出位的信号状态填充。输入参数 n 提供数值表示循环移动的位数,OUT 是循环移位的操作结果。其文本化语言语法格式如下所示,
OUT:= ROL (IN, n)
【例 9.38】创建一个 POU,试对比按位左移和循环左移的区别,将 16 进制 WORD 型变量 wWord1 分别采用两种不同的左移方式移动同样的位数,试比较结果。

图 9.49 按位左移循环左移比较程序举例

图 9.50 循环左移 4 位程序举例
通过例 9.38 不难看出,使用循环右移后的输出 wWord3 的 b0~b3 位并不是将空位补 0,而是将输入数据 wWord1 中的 b12~b15 中的 1010 补到 b0~b3 位,其详细过程详见 9.50 图示。
循环移位指令的总位数同样也会受到输入变量的数据类型的影响。如果输入变量是常量,将会取长度最小的数据类型。而输出变量的数据类型则不会对算术运算产生影响,通过如下例子鉴别两者的区别。
【例 9.39】请比较下面 16 进制数的循环左移的运算,尽管 byte 和 word 形式的输入变量值相等,但根据输入变量的数据类型不同(BYTE 或 WORD),erg_byte 和 erg_word 将得到不同的结果。
VAR
in_byte: BYTE:=16#45;
in_word: WORD:=16#45;
erg_byte : BYTE;
erg_word : WORD;
n: BYTE :=2;
END_VAR
erg_byte:=ROL(in_byte,n); (* 结果为 21 *)
erg_word:=ROL(in_word,n); (* 结果为 276 *)

图 9.51 BYTE 与 WORD 变量循环左移比较
如图 9.51 所示,当 BYTE 类型变量的 b6,b7 位左移 2 位后移至输出数据中的 b0 和 b1 位,最终的数据为 十进制的 21。而当 WORD 类型变量的 b6,b7 位左移两位后,移至输出数据中的 b8 和 b9 位,原数据的 b14 和 b15 位为 0,左移后,移至输出数据的 b0 和 b1 位,故最终的结果为 十 进制的 276。
-
循环右移 ROR
功能:对操作数进行按位循环右移,右边移出的位直接补充到左边最高位。
语法:允许的数据类型:BYTE、WORD、DWORD。使用该指令可以将输入 IN 中的全部内容循环的逐位右移,空出的位用移出位的信号状态填充。输入参数 n 提供数值表示循环移动的位数,OUT 是循环移位的操作结果,其文本化语言语法格式如下所示,
OUT: = ROR (IN, n)
【例 9.40】利用循环按位右移指令完成 WORD 类型输入变量 wWord1 的当前值循环右移 5 位,输出结果赋值给 wWord2,程序如 9.52 所示,样例程序请参考\第9章\25 ROR_WORD\。

图 9.52 循环按位右移程序举例

图 9.53 循环按位右移 5 位过程
最终程序的运行结果为 十 进制的 4104,程序将原来 wWord1 的低 5 位 b0~b4 移至 wWord2 中的 b11~b15,其程序移位过程如图 9.53 所示。
【例 9.41】利用循环右移指令,设计一个 16 位的闪灯程序,按 2s 的频率逐一向右闪烁。

图 9.54 循环按位右移闪灯程序
通过通电延时定时器的输出每 2 秒触发一次指令循环右移指令,其程序如图 9.54 所示,样例程序请参考\第9章\26 ROR_LIGHT\。
9.5 运算指令
运算指令针对操作数进行运算,同时产生运算结果。运算指令是一种专门处理数据运算的特殊符号,数据变量结合的运算指令形成完整的程序运算语句。本节会针对 MetaFacture 中常用的运算指令做详细介绍,包括赋值指令、算术运算指令、数学运算指令和地址运算指令。
9.9.1 赋值指令
赋值指令是 MetaFacture 中最常用的指令,在实际应用中,他实现的功能是将一个变量的数据传送给另外一个变量中。
-
赋值指令 MOVE
功能:将一个常量或者变量的值赋给另外一个变量,也是 MetaFacture 中最常用的指令,赋值指令表的图形化及文本化指令表详见表 9-32 所示。
表 9-32 赋值指令的图形化及文本化指令表
|
赋值指令
|
图形化语言
|
文本化语言
|
说明
|
|
赋值指令
|
![]() |
:=
|
相等
|
如使用文本化指令,实现例 9.42 中的代码为:
nVar2:=nVar1;
9.9.2 算术运算指令
+、-、*、/、MOD 运算指令都算算术运算指令,分别用于进行加、减、乘、除和求余数运算。下面对这几种算术运算指令进行详细的讲解。其指令详细详见表 9-33 所示。
表9-33 算术运算指令的图形化及文本化指令表
|
算术运算指令
|
图形化语言
|
文本化语言
|
说明
|
|
算术运算指令
|
![]() |
+
|
相加
|
![]() |
-
|
相减
|
|
![]() |
*
|
相乘
|
|
![]() |
/
|
相除
|
|
![]() |
MOD
|
取余数
|
-
加法运算 ADD
功能:加法运算指令,两个(或者多个)变量或常量相加。两个时间变量也可相加,结果是另一个时间变量。
语法:指令可以将输入变量 IN0 的值直至 INn 的值做加法运算,将其结果赋值至 OUT。加法运算指令支持如下的变量类型,BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、(L)REAL、TIME 和常数。其文本化语言语法格式如下所示,
OUT := IN0 +…+INn
【例 9.43】创建一个 POU,声明两个整型变量 iVar1 和 iVar2,并将 iVar1 赋值为 2014,然后使 iVar2 的值为 iVar1 与 iVar1 相加后的值,具体代码如下。
VAR
iVar1:INT:=2014;
iVar2:INT;
END_VAR
iVar2:=iVar1+iVar1;
程序的运行结果为 iVar2 等于 4028。
【例 9.44】在实际工程中,经常需要记录操作的次数,使用 ST 程序语言,当数字累加到 10 时,将该累计变量清零。
如下为使用 ST 语言的程序实现。通过上升沿触发功能块对被加数 iCounter 进行累加。
VAR
bCalStart: BOOL;
FB_StartTrigR_TRIG:R_TRIG;
iCounter:word;
END_VAR
FB_StartTrigR_TRIG(CLK:=bCalStart); IF FB_StartTrigR_TRIG.Q THEN iCounter:=iCounter+1;
END_IF
IF iCounter=10 THEN iCounter:=0;
END_IF
样例程序请参考\ADD\。
注意:
TIME 型变量也可使用加法功能,两个 TIME 变量相加得到一个新的时间。
例 :t#45s + t#50s = t#1m35 s。
被选择的输出数据类型应可存储输出结果,否则可能引起数据错误。
-
减法运算 SUB
功能:减法运算指令,两个变量或常量相减。语法:指令可以将输入变量 IN0 的减去 IN1 的值,将其结果赋值至 OUT。减法运算指令支持如下的变量类型,BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、(L)REAL、TIME 和常数。其文本化语言语法格式如下所示,
OUT := IN0 –IN1
【例 9.45】创建一个 POU,声明两个浮点数变量 rVar1 和 rVar2,分别赋值 3.14 和 10,此外再声明一个 rResult 变量,将其值为 rVar2 减去 rVar1 之后得到的值,具体代码如下。
VAR
rVar1:REAL:=3.14;
rVar2:REAL:=10;
rResult:REAL;
END_VAR
rResult:=rVar2-rVar1;
程序的运行结果为 rResult 等于 6.86。
注意:
TIME 型变量也可使用减法功能,两个 TIME 变量相减得到一个新的时间。
例 :t#1m35s - t#50s = t#45s ,但时间结果不能有负值。
TOD 型变量也可使用减法功能,两个 TOD 型相减得到一个新的 TIME 型数据。
例 :TOD#45:40:30- TOD#22:30:20=T#1390m10s0ms ,但时间结果不能有负值。
-
乘法运算 MUL
功能:乘法运算指令,两个(或者多个)变量或常量相乘。
语法:指令可以将输入变量 IN0 的值直至 INn 的值做乘法运算,将其乘积赋值至 OUT。乘法运算指令支持如下的变量类型,BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、(L)REAL、TIME、TOD 和常数。其文本化语言语法格式如下所示,
OUT := IN0 *…*INn
【例 9.46】创建一个 POU,声明两个整形变量 iVar1 和 iVar2,并分别赋值为 10 和 2,再声明一个整型变量 iResult,使其结果为 iVar1 和 iVar2 的乘积,具体实现代码如下。
VAR
iVar1:INT:=10;
iVar2:INT:=2;
iResult:INT;
END_VAR
iResult:=iVar1*iVar2;
程序的运行结果为 iResult 等于 20。
-
除法运算 DIV
功能:除法运算指令,两个变量或常量相除。
语法:指令可以将输入变量 IN0 的除以 IN1 的值,将其得到商值赋值至 OUT。除法运算指令支持如下的变量类型,BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、LREAL 和常数。其文本化语言语法格式如下所示,
OUT := IN0 / IN1
【例 9.47】创建一个 POU,声明两个整型变量 iVar1 和 iVar2,并分别赋值为 10 和 2,再声明一个整型变量 iResult,使其值为 iVar1 除以 iVar2 得到的值,具体实现代码如下。
VAR
iVar1:INT:=10;
iVar2:INT:=2;
iResult:INT;
END_VAR
iResult:=iVar1/iVar2;
程序的运行结果为 iResult 等于 5。
注意:
在工程 中使用 DIV 指 令 时,可 使用 CheckDivByte、CheckDivWord 、CheckDivDWord 和
CheckDivReal 等指令检查除数是否为零,避免了除数为零的现象
-
求余数运算 MOD
功能:变量或常量相除取余,结果为两数相除后的余数,是一个整型数据。
语法:求余数运算指令 MOD 指令可以将输入变量 IN0 与 IN1 相除的余数赋值给 OUT,通常使用该运算指令创建余数在特定范围内的等式。求余数运算指令支持如下的变量类型,BYTE、 WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、LREAL 和常数。其文本化语言语法格式如下所示,
OUT := IN0 MOD IN1;
【例 9.48】创建一个 POU,声明两个整型变量 iVar1 和 iVar2,并分别赋值为 44 和 9,再声明一个整型变量 iResult,使其值为 iVar1 与 iVar2 求余运算之后的值,具体实现代码如下。
VAR
iVar1:INT:=44;
iVar2:INT:=9;
iResult:INT;
END_VAR
iResult:=iVar1 MOD iVar2;
程序的运行结果为 iResult 等于 8。
9.9.3 数学运算指令
数学运算指令包括三角函数运算指令,高级算术指令,相关指令表如表 9-34 所示。
表9-34 数学运算指令的图形化及文本化指令表
|
数学运算指令
|
图形化语言
|
文本化语言
|
说明
|
|
数学算术运算指令
|
![]() |
ABS
|
绝对值指令
|
![]() |
SQR
|
平方根指令
|
|
![]() |
EXP
|
指数指令
|
|
![]() |
LN
|
自然对数指令
|
|
![]() |
LOG
|
常用对数指令
|
|
![]() |
SIN
|
正弦指令
|
|
![]() |
COS
|
余弦指令
|
|
![]() |
ACOS
|
反余弦指令
|
|
|
|
|
|
|
|
|
![]() |
ASIN
|
反正弦指令
|
![]() |
TAN
|
正切指令
|
|
![]() |
ATAN
|
反正切指令
|
-
绝对值 ABS
功能:这个函数指令是用来计算一个数的绝对值,与正负号数符号没有关系。
语法:绝对值运算指令支持如下的变量类型,BYTE、WORD、DWORD、SINT、USINT、
INT、UINT、DINT、UDINT、REAL、LREAL 和常数。其文本化语言语法格式如下所示,
OUT := ABS (IN);
【例 9.49】ABS 函数示例。
VAR
iVar1:INT:=-44;
iResult:INT;
END_VAR
iResult:=abs(iVar1);
程序的运行结果为 iResult 等于 44。
-
平方根 SQRT
功能:非负实数的平方根。
语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := SQRT(IN);
【例 9.50】SQRT 函数示例。
VAR
rVar1:REAL:=16;
rResult:REAL;
END_VAR
rResult:=SQRT(rVar1);
程序的运行结果为 rResult 等于 4。
-
指数函数 EXP
功能:返回 e(自然对数的底)的幂次方,e 是一个常数为 2.71828 的数。
语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := EXP(IN);
【例 9.51】EXP 函数示例。
VAR
rVar1:REAL:=2;
rResult:REAL;
END_VAR
rResult:=EXP(rVar1);
程序的运行结果为 rResult 等于 7.389056。
-
自然对数 LN
功能:返回一个数的自然对数。自然对数以常数项 e (2.71828182845904) 为底。语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := LN (IN);
【例 9.52】LN 函数示例。
VAR
rVar1:REAL:=45;
rResult:REAL;
END_VAR
rResult:=LN(rVar1);
程序的运行结果为 rResult 等于 3.80666。
-
以 10 为底的对数 LOG
功能:返回底为 10 数的对数。
语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := LOG(IN);
【例 9.53】LOG 函数示例。
VAR
rVar1:REAL:=314.5;
rResult:REAL;
END_VAR
rResult:=LOG(rVar1);
程序的运行结果为 rResult 等于 2.49762。
-
正弦函数 SIN
功能:正弦函数。
语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := SIN(IN);
【例 9.54】SIN 函数示例。
VAR
rVar1:REAL:=0.5;
rResult:REAL;
END_VAR
rResult:=SIN(rVar1);
程序的运行结果为 rResult 等于 0.479426。
【例 9.55】下列程序中通过算术指令完成某角度的正弦值运算。在使用三角函数指令之前先将角度值换算成弧度值,然后再用 SIN 指令求正弦值。程序如图 9.56 所示。

图 9.56 正弦 SIN 指令程序示例
-
余弦函数 COS
功能:余弦函数。
语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := COS(IN);
【例 9.56】COS 函数示例。
VAR
rVar1:REAL:=0.5;
rResult:REAL;
END_VAR
rResult:=COS(rVar1);
程序的运行结果为 rResult 等于 0.877583。
-
反余弦函数 ACOS
功能:余弦弧度(反余弦函数)。
语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := ACOS(IN);
【例 9.57】ACOS 函数示例。
VAR
rVar1:REAL:=0.5;
rResult:REAL;
END_VAR
rResult:=ACOS(rVar1);
程序的运行结果为 rResult 等于 1.0472。
-
反正弦函数 ASIN
功能:正弦弧度(反正弦函数)。
语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := ASIN(IN);
【例 9.58】ASIN 函数示例。
VAR
rVar1:REAL:=0.5;
rResult:REAL;
END_VAR
rResult:=ASIN(rVar1);
程序的运行结果为 rResult 等于 0.523599。
-
正切函数 TAN
功能:正切函数。
语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := TAN(IN);
【例 9.59】TAN 函数示例。
VAR
rVar1:REAL:=0.5;
rResult:REAL;
END_VAR
rResult:= TAN (rVar1);
程序的运行结果为 rResult 等于 0.5463025。
-
反正切函数 ATAN
功能:正切弧度(反正切函数)。
语法:输入变量 IN 可以是 BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、LREAL 和常数,但输出必须是 REAL 或 LREAL 类型。其文本化语言语法格式如下所示,
OUT := ATAN(IN);
【例 9.60】ATAN 函数示例。
VAR
rVar1:REAL:=0.5;
rResult:REAL;
END_VAR
rResult:= ATAN (rVar1);
程序的运行结果为 rResult 等于 0.463648。
9.9.4 地址运算指令
在实际应用中,有很多情况涉及到内存地址的指令,比如取数组的内存首地址,需要了解该数组在内存中占了多少个字节等相关信息,所涉及的指令如表 9-35 所列,在本节会一一介绍。
表9-35 地址运算指令的图形化及文本化指令表
|
选择运算指令
|
图形化语言
|
文本化语言
|
说明
|
|
选择运算指令
|
![]() |
SIZEOF
|
数据类型大小
|
![]() |
ADR
|
地址操作符
|
|
![]() |
BITADR
|
位地址操作符
|
-
数据类型大小 SIZEOF
功能:执行这个功能以确定给出的数据类型所需要的字节数量。简单的说其作用就是返回一个对象或者类型所占的内存字节数。
语法:SIZEOF 的返回值的是一个无符号值,类型的返回值将会被用于查找变量 IN0 的大小, OUT 输出值的单位为字节,IN0 可以为任何数据类型。其文本化语言语法格式如下所示。返回值的类型是隐式数据类型,它会根据实际数据值来决定,具体详见表 9-36 所示。
OUT := SIZEOF(IN0);
表 9-36 SIZEOF 的返回数据类型
|
SIZEOF的返回值X
|
隐式数据类型
|
|
0 <= size of x <256
|
USINT
|
|
256 <= size of x <65536
|
UINT
|
|
65536 <= size of x <4294967296
|
UDINT
|
|
4294967296 <= size of x
|
ULINT
|
【例9.61】使用SIZEOF 指令取数组占用内存大小的举例,程序如下所示。
ST 语言的示例:
VAR
arr1:ARRAY[0..4] OF INT;
var1:INT;
END_VAR
var1 := SIZEOF(arr1);
IL 语言的示例:

程序将结果赋值给 var1,最终 var1 等于 10,因为 arr1 数组共由 5 个 INT 整型元素构成, SIZEOF 的结果单元为 BYTE,故最终程序运行结果为共有 10 个 BYTE,表示 arr1 占用 10 个字节的内存。
-
地址操作符 ADR
功能:取得输入变量的内存地址,并输出。该地址可以在程序内当作指针使用,也可以作为指针传递给函数。
语法:ADR 操作符其返回值为一个 DWORD 的地址变量,IN0 可以为任何数据类型。其文本化语言语法格式如下所示,
OUT :=ADR(IN0);
ADR 的返回值仅是变量的内存地址。该内存地址可以存放的数据长度为 1 个 BYTE。可以通过内容操作符“^” 提取对应地址中的内容,如需获取 var_int1 的内存地址,将其地址赋值给指针变量,再将其对应地址中的具体内容通过“^”操作符提取出来并赋值给 var_int2。实现程序如下所示,
pt := ADR(var_int1);
var_int2:= pt^;
【例 9.62】使用 ADR 指令取数组的举例,程序如下所示。
ST 语言的示例:
VAR
arr1:ARRAY[0..4] OF INT;
dwVar:DWORD;
END_VAR
dwVar:=ADR(arr1);
IL 语言的示例:

【例 9.63】使用 ADR 指令取数组的举例,程序如下所示。ADR 指令
ST 语言的示例:
VAR
arr1:ARRAY[0..4] OF INT;
dwVar:DWORD;
END_VAR
dwVar:=ADR(arr1);
【例 9.64】使用 ADR 指令取数组的举例,程序如下所示。
ST 语言的示例:
pt:POINTER TO INT; var_int1:INT; var_int2:INT; pt := ADR(var_int1); var_int2:=pt^;
-
位地址操作符 BITADR
功能:返回分配变量的位地址信息偏移量。
语法:BITADR 操作符其返回值为一个 DWORD 的地址变量,IN0 可以为任何数据类型。其文本化语言语法格式如下所示,
OUT :=BITADR(IN0);
ADR 的返回值仅是变量的内存地址。该内存地址可以存放的数据长度为 1 个 BYTE。可以通过内容操作符“^” 提取对应地址中的内容,如需获取 var_int1 的内存地址,将其地址赋值给指针变量,再将其对应地址中的具体内容通过“^”操作符提取出来并赋值给 var_int2。实现程序如下所示,
BITADR 以 DWORD 变量类型返回位偏移数值地址。注意偏移值取决于选项类型地址是否可以从目标系统中获得。DWORD 最大值定义内存区域如表 9-37 所示:
表9-37 BITADR各地址区偏移地址
|
地址区
|
起始地址
|
说明
|
|
Mcmory
|
16x40000000
|
%M
|
|
Input
|
16x80000000
|
%I
|
|
Output
|
16xC0000000
|
%Q
|
【例 9.65】使用 BITADR 指令取位地址信息的举例,程序如下所示。
ST 语言的示例:
VAR
var1 AT %IX2.3:BOOL;
bitoffset: DWORD;
END_VAR
bitoffset:=BITADR(var1);
IL 语言的示例:

运行结果为 十进制的 2147483667, %IX2.3 中的“2”为 2 个 Byte,“.3”为第 4 个 Bit,所以其地址等于 2*8+4=20。将 10 进制的 20 转换为 16 进制的 14。又因为对应 I 区的首地址是从 80000000 开始存放的,故不难理解,16 进制的 14 对应的实际地址是 16#80000013,示意图如图 9.57 所示。

图 9.57 BITADR 示意图
9.6 数据转换指令
9.6.1 数据类型转换指令
语法:<TYPE1>_TO_<TYPE2>
严禁将“较大的”数据类型隐含地转换为“较小的”数据类型使用,因当从较大数据类型转为较小数据类型时,有可能丢失信息。
如被转换的值超出目标数据类型的存储范围,则这个数的高字节将被忽略。例:将 INT 类型转换为 BYTE 类型,或将 DINT 类型转换为 WORD 类型。
<TYPE>_TO_STRING 的转换中,字符串是从左边开始生成的。如果定义的字符串长度小于
<TYPE>的长度,右边部分会被截去。
-
BCD 码与整型数据相互转换
BCD(Binary Coded Decimal…BCD)即用 4 位 2 进制数来并列表示 10 进制数中各个位数的值。例如,BIN 数据中按照如图 9.58 方式用 BCD 数据 0000 0001 0101 0111(343)来表示 10 进制数“157”。

图 9.58 BCD 示例说明
BCD 数据保存在 16 位存储器内时,可以处理 0~9999(4 位的最大值)的数值。各个位的权重如下图 9.59 所示。

图 9.59 BCD 用 10 进制表示的各数值权重
MetaFacture 用于 BCD 码与整型的互相转换指令详见表 9-38。使用该转换函数前需要先添加 util.library 库。
表 9-38 BCD 码与整数的互相转换指令
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
BCD码与整数的互相转换指令
|
![]() |
BCD_TO_BYTE
|
BCD转BYTE
|
![]() |
BCD_TO_DWORD
|
BCD转DWORD
|
|
![]() |
BCD_TO_INT
|
BCD转INT
|
|
![]() |
BCD_TO_WORD
|
BCD转WORD
|
|
![]() |
BYTE_TO_BCD
|
BYTE转BCD
|
|
![]() |
DWORD_TO_BCD
|
DWOED转BCD
|
|
![]() |
INT_TO_BCD
|
INT转BCD
|
|
![]() |
WORD_TO_BCD
|
WOED转BCD
|
【例 9.66】使用 ST 编程语言,将 BCD 码 73 转换为整型数据。
定义BCD_TO_INT函数:
FUNCTION BCD_TO_INT : INT
VAR_INPUT
bcdValue: BYTE; // 输入BCD码(BYTE类型,范围0x00-0xFF)
END_VAR
VAR
tens: INT; // 十位数字
ones: INT; // 个位数字
END_VAR
tens := SHR(bcdValue, 4); // 提取十位(高4位)
ones := bcdValue AND 16#0F;// 提取个位(低4位)
IF tens > 9 OR ones > 9 THEN // 验证是否为有效BCD码
BCD_TO_INT := -1; // 返回-1表示错误
ELSE
BCD_TO_INT := tens * 10 + ones; // 返回整数结果
END_IF;
// 定义PLC_PRG:
PROGRAM PLC_PRG
VAR
inputBCD: BYTE; // 输入BCD码
outputInt: INT; // 转换后的整数
END_VAR
inputBCD := 73;
outputInt := BCD_TO_INT(inputBCD);
IF outputInt = -1 THEN
// 此处添加错误处理逻辑(如报警或复位)
END_IF;

图 9.60 BCD 转 INT 应用举例
如上图 9.60 所示,使用 BCD_TO_INT 指令进行转换,因为 73 转换为 2 进制后的结果为 0100 1001,故将其转换为 BCD 后的结果为 49。
【例 9.67】使用 ST 编程语言,将整型数据 73 转换为 BCD 码。
定义 INT_TO_BCD函数:
FUNCTION INT_TO_BCD : WORD
VAR_INPUT
InputInt : INT; // 输入的整数
END_VAR
VAR
TempValue : INT;
BCDResult : WORD := 0;
Place : INT := 1;
END_VAR
TempValue := InputInt;
WHILE TempValue > 0 DO
BCDResult := BCDResult + ((TempValue MOD 10) * Place); // 获取当前最低位数字
TempValue := TempValue / 10;// 去掉最低位
Place := Place * 16;// 移动到下一个BCD位
END_WHILE;
INT_TO_BCD := BCDResult;
定义PLC_PRG:
PROGRAM PLC_PRG
VAR
InputValue : INT := 73; // 输入的整型数据
OutputBCD : WORD; // 用于存储转换后的 BCD 码
END_VAR
OutputBCD := INT_TO_BCD(InputValue);

图 9.61 INT 转 BCD 应用举例
如上图 9.61 所示,采用 INT_TO_BCD 指令进行转换。程序将 10 进制的 73 转换为 BCD 码后的结果为 0111 0011,故最终 BCD 码十进制的表示结果为 115。
【例 9.68】工业控制中经常会遇到数据设定及数据显示的情况,此时通常需要通过 BCD 码与整型数据转换来实现。如图 9.62 所示,用户利用数字输入按钮输入数据 1942,程序内需要将该数进行加法计算,加 752,将结果显示在 7 段码数据显示窗中。
![]() |
![]() |
a)数字输入开关的输入信号 b)7 段显示器(数字显示器)的输出信号
图 9.62 输入信号与输出显示
程序如图 9.63 所示,有效区为红色框内段程序,梯形图第 1 句和第 3 句为了便于理解,实际应用中不要此转换指令。
当用户通过拨码开关键入 1942 时,在程序内实际收到对应的 BCD 数据为 6466,故需要将6466 转换为实际整型数据进行逻辑运算。由于 BCD_TO_INT 输出的是为 BYTE 类型变量,如使用 6466 转换后会使数据溢出,故在此需要使用 WORD 类型的输出指令 BCD_TO_WORD 将其 BCD 数据还原成整型数据。转换后能在程序内进行正常的逻辑运算,在此进行了加法运算,还原有效数据,通过运算将结果转换为 7 段显示器能识别的 BCD 数据最终输出。

图 9.63 输入信号与输出显示程序举例
样例程序详见\第9章\27 BCD_TO_INT\。
-
BOOL_TO_<TYPE> 布尔类型转换数据
功能:把布尔数据类型转换为其它数据类型。
支持数据类型 :BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、TIME、DATE、TOD、DT 和 STRING。
输出为数字类型时 :如果输入是 TRUE,则输出为 1。如果输入是 FALSE,则输出为 0。
输出为字符串类型时 :如果输入是 TRUE,则输出字符串'TRUE'。如果输入是 FALSE,则输出为字符串'FALSE'。
【例 9. 69】BOOL_TO_<TYPE>示例如下表 9-39 所示。
表9-39 BOOL_TO_<TYPE>转换梯形图指令举例
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
BOOL_TO
|
![]() |
i:=BOOL_TO_INT(TRUE);
|
1
|
![]() |
str:=BOOL_TO_STRING(TRUE);
|
'TRUE'
|
|
![]() |
t:=BOOL_TO_STIME(TRUE);
|
T#1ms
|
|
![]() |
tof:=BOOL_TO_TOD(TRUE);
|
TOD#0:0:0.001
|
|
![]() |
dat:=BOOL_TO_DATE(FALSE);
|
D#1970-1-1
|
|
![]() |
dandt:=BOOL_TO_DT(TRUE);
|
DT#1970-1-1-0:0:1
|
-
BYTE_TO_<TYPE> 字节类型转换数据
功能:把字节类型转换为其它数据类型。支持数据类型:BOOL、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、TIME、DATE、TOD、DT 和 STRING。
输出为 BOOL 时 :输入不等于 0 时,输出为 TRUE。输入等于 0 时,输出为 FALSE。
输出为 TIME 或 TOD 时 :输入将以毫秒值进行转换。输出为 DATE 或 DT 时 :输入将以秒值进行转换。
【例 9.70】BYTE_TO_<TYPE>示例如下表 9-40 所示。
表9-40 BYTE_TO_<TYPE>转换梯形图指令举例
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
BYTE_TO
|
![]() |
bVarbool:=BYTE_TO_BOOL(255);
|
TRUE
|
![]() |
iVarint:=BYTE_TO_INT(255);
|
255
|
|
![]() |
tVartime:=BYTE_TO_TIME(255);
|
T#255ms
|
|
![]() |
dtVardt:=BYTE_TO_DT(255);
|
DT#1970-1-1-0:4:15
|
|
![]() |
rVarreal:=BYTE_TO_REAL(255);
|
255
|
|
![]() |
stVarstring:=BYTE_TO_STRING(255);
|
'255'
|
-
<整型数据> _TO_<TYPE>整数类型转换指令
功能:把整数类型数据转换为其它数据类型。
支持数据类型:BOOL、BYTE、SINT、WORD、DWORD、USINT、INT、UINT、DINT、
UDINT、REAL、TIME、DATE、TOD、DT 和 STRING。
输出为 BOOL 时:输入不等于 0 时,输出为 TRUE。输入等于 0 时,输出为 FALSE。
输出为 TIME 或 TOD 时,输入将以毫秒值进行转换。
输出为 DATE 或 DT 时 :输入将以秒值进行转换。
【例 9.71】由于整数类型很多,转换过程相似,故以 WORD_TO_<TYPE>举例,如表 9-41 所示。
表9-41 <整型数据>_TO_<TYPE>转换梯形图指令举例
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
<整型数据>_TO
|
![]() |
iVarsint:=WORD_TO_USINT(4836);
|
228
|
![]() |
iVartime:=WORD_TO_TIME(4836);
|
T#4s836ms
|
|
![]() |
dtVardt:=WORD_TO_DT(4836);
|
DT#1970-1-1-1:20:36
|
-
REAL_TO_<TYPE>实数类型转换指令
功能:把浮点数转换为其它类型数据。把浮点数转换为其它类型数据时,先将值四舍五入成整数值,然后转成新的量类型。
支持数据类型:BOOL、BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、TIME、DATE、TOD、DT 和 STRING。
输出为 BOOL 时:输入不等于 0 时,输出为 TRUE。输入等于 0 时,输出为 FALSE。
输出为 TIME 或 TOD 时:输入将以毫秒值进行转换。
输出为 DATE 或 DT 时 :输入将以秒值进行转换。
【例 9.72】REAL_TO_<TYPE>示例如下表 9-42 所示。
表9-42 REAL_TO_<TYPE>转换梯形图指令举例
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
REAL_TO
|
![]() |
iVarint:=REAL_TO_INT(1.5);
|
2
|
-
TIME_TO_<TYPE> 时间类型转换指令
功能:把时间型数据转换为其它类型数据,时间在内部以毫秒为单位存储成 DWORD 类型(对于 TIME_OF_DAY 变量从凌晨 00:00 开始)。
支持数据类型:BOOL、BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、TIME、DATE、TOD、DT 和 STRING。
输出为 BOOL 时:输入不等于 0 时,输出为 TRUE。输入等于 0 时,输出为 FALSE。
【例 9.73】TIME_TO_<TYPE>示例如下表 9-43 所示。
表9-43 TIME_TO_<TYPE>转换梯形图指令举例
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
TIME_TO
|
![]() |
sVarstring:=TIME_TO_STRING(T#12MS);
|
'T#12ms'
|
![]() |
dVardword:=TIME_TO_DWORD(T#5MS);
|
5
|
-
DATE_TO_<TYPE> 日期类型转换指令
功能:把日期型数据转换为其它类型数据,日期在内部以秒为单位存储,时间从 1970 年 1 月 1日开始。
支持数据类型:BOOL、BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、TIME、DATE、TOD、DT 和 STRING。
输出为 BOOL 时:输入不等于 0 时,输出为 TRUE。输入等于 0 时,输出为 FALSE。
【例 9.74】DATE_TO_<TYPE>示例如下表 9-44 所示。
表9-44 DATE_TO_<TYPE>转换梯形图指令举例
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
DATE_TO
|
![]() |
sVarstring:=DATE_TO_STRING(D#1970-01-01);
|
'D#1970-01-01'
|
![]() |
sVarint :=DATE_TO_INT(D#1970-01-15);
|
29952
|
-
DT_TO_<TYPE>日期时间类型转换指令
功能:把日期时间型数据转换为其它类型数据,日期在内部以秒为单位存储,时间从 1970 年 1 月 1 日开始。
支持数据类型:BOOL、BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、TIME、DATE、TOD、DT 和 STRING。
输出为 BOOL 时: 输入不等于 0 时,输出为 TRUE。输入等于 0 时,输出为 FALSE。
【例 9.75】DT_TO_<TYPE>示例如下表 9-45 所示。
表9-45 DT_TO_<TYPE>转换梯形图指令举例
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
DT_TO
|
![]() |
byVarbyte:= DT_TO_BYTE(DT#1970-01-19-05:05:05);
|
129
|
![]() |
sVarstr:= DT_TO_ STRING (DT#1998-02-
13-05:05:06);
|
‘DT#1998-02-13-
05:05:06’
|
-
TOD_TO_<TYPE> 时间类型转换指令
功能:把时间型数据转换为其它类型数据,日期在内部以毫秒为单位进行转化。
支持数据类型:BOOL、BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、UDINT、REAL、TIME、DATE、TOD、DT 和 STRING。
输出为 BOOL 时:输入不等于 0 时,输出为 TRUE。输入等于 0 时,输出为 FALSE。
【例 9.76】TOD_TO_<TYPE>示例如下表 9-46 所示。
表9-46 TOD_TO_<TYPE>转换梯形图指令举例
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
TOD_TO
|
![]() |
iVarusint:=TOD_TO_USINT(TOD#10:11:40);
|
96
|
![]() |
tVartime:=TOD_TO_TIME(TOD#10:11:40);
|
T#10h11m40s
|
|
![]() |
dtVardt:=TOD_TO_DT(TOD#10:11:40);
|
DT#1970-1-1-10:11:40
|
|
![]() |
rVarreal:=TOD_TO_REAL(TOD#10:11:40);
|
3.67E+07
|
-
STRING_TO_<TYPE> 字符类型转换指令
功能:把字符串转换为其它类型数据,字符串型变量必须包含一个有效的目标变量值,否则转换结果为 0。
支持数据类型:BOOL、BYTE、WORD、DWORD、SINT、USINT、INT、UINT、DINT、 UDINT、REAL、TIME、DATE、TOD、DT 和 STRING。
【例 9.77】STRING_TO_<TYPE>示例如下表 9-47 所示。
表9-47 STRING_TO_<TYPE>转换梯形图指令举例
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
STRING_TO
|
![]() |
wVarword:=STRING_TO_WORD('Metafacture');
|
0
|
![]() |
tVartime:=STRING_TO_TIME('T#128ms');
|
T#128ms
|
-
取整 TRUNC
功能:将数据截去小数部分,只保留整数部分。
支持数据类型:输入为 REAL 型,输出为 INT、WORD、DWORD 型。
【例 9.78】TRUNC 取整指令示例如下表 9-48 所示。
表9-48 取整指令
|
转换指令
|
图形化语言
|
文本化语言
|
结果
|
|
TRUNC
|
![]() |
iVarint:=TRUNC(1.7);
|
1
|
![]() |
iVarint1:=TRUNC(-1.2);
|
-1
|
注意:
当从较大数据类型转为较小数据类型时,有可能丢失信息。
本指令只是截取整数部分,如果想四舍五入取整,可使用 REAL_TO_INT 指令。