【TwinCAT3教程】IEC61131-3编程基础

news2024/9/24 11:21:24

在开发可编程序控制器(PLC)的早期阶段没有统一的标准,这种编程语言不统一的情况,给用户带来极大的不方便,近几年由于自动化系统的发展,IEC的第七个工作组制定了IEC(International Electro technical Commission) 61131-3标准,IEC61131-3本身只作为PLC的编程指导,而不是强制的规则。它是IEC 61131国际标准的第三部分,是第一个为工业自动化控制系统的软件设计提供标准化编程语言的国际标准。

 IEC61131-3的优势:

  • 国际上承认的标准
    • 逐步的在不远的将来所有供应商将采用它
    • 统一的结构, 语言和操作处理方式将来自所有供应商
  • 它节省你的时间
    • 统一的软件模式和数据类型概念
    • 对来自不同的PLC类型你只需学习一次
    • 减少了误解和错误
    • 标准的函数和功能块
    • 测试软件的可重复使用性
  • 支持安全和高质量编程设计 
    • 轻松和舒适的结构
    • 数据类型避免了编程错误
  • 对每个问题提供了最佳编程语言
    • 一致的5种编程语言规范
    • 文本和图形语言
    • 高级语言的可用性
    • 不同语言混合编程

 一、IEC 61131 软件模型

配置Configuration

  • 最高层,描述了整个控制系统的架构。
  • 一个配置可被比作一个可编程控制器系统。
  • 在一个配置里可以定义一个或几个资源。
  • 在TwinCAT: 就是中 一个或多个PLC

资源Resource

  • 一个配置有一个或多个资源
  • “实质”PLC: 自己的全局变量, POU, 任务等.
  • 在TwinCAT: 就是一个 PLC 运行核 (Runtime)

任务Task

  • 对一个相关程序的周期的执行,实施控制单元
  • 一个资源有一个或多个任务
  • 有优先级时序排列(0~3,共四个级别)
  • 优先权和循环时间
  • 任务调用一个或多个程序
  • 任务决定了所关联程序的时间调度。

程序Program

  • 程序是根据控制器过程的需要,包含了函数和功能块的一个逻辑组合的POU。
  • 由任务调用程序
  • 可以调用: 功能块(Functon Block)、函数(Function)和其它程序(Program)。
    • 局部变量: 静态, 即局部变量的数据可以在下个周期使用。
    • 输入: 一般是没有输入的变量, 在VAR_INPUT可以定义输入变量的。
    • 输出: 一般是没有输出的变量, 在VAR_OUTPUT可以定义输出变量的。
    • 输入输出型变量:可以在VAR_IN_OUT定义的。
    • 监视: 在线状态下变量的值是实时可见的。

功能块(FB) Function Block

  • 由程序或者其他功能块调用
  • 可以调用: 功能块(Functon Block)和函数(Function)
  • FB 有运算法则:每次FB被执行,就是运行一段程序编码
    • 局部变量: 静态, 即局部变量数据可以在下个运行周期使用,多个功能块 中,每个FB都有自己的局部变量。
    • 输入: 多个输入,在VAR_INPUT中定义。
    • 输出: 多个输出,在VAR_OUTPUT中定义。
    • 输入输出:多个输入输出变量。在VAR_IN_OUT中定义。
    • 监视:在线状态下对于每个指定的功能块,局部变量是可见的。

函数Function

  • 由程序、功能块和其他函数调用
  • 可以调用:函数(Function)
  • 函数有运算法则:每次函数被执行,就是运行一段程序编码
    • 局部变量: 临时的, 即局部变量数据仅在当前function 执行时可以使用, 之后这个数据区就被用于其它functions。
    • 输入: 多个输入变量,在VAR_INPUT中定义。
    • 输出:只有1个!
    • 输入输出:可以有多个输入输出型变量,在 VAR_IN_OUT中定义。
    • 监视: 在线状态下仅能看到 “???”。使用断点可以监视其局部变量值。
功能块和函数之间的区别
内存地址输出变量调用
功能块全部数据分配内存地址多个输出变量或没有输出变量可调用功能块或函数
函数没有指定的内存分配地址一个输出变量可调用函数,但不能调用功能块

二、标识符、关键字和注释

2.1标识符

  • 字母(A到Z,a到z)、数字(0到9)或下划线组成
  • 首字符必须是字母者下划线
  • 字母不分大小写(abc = Abc = ABC)
  • 不可以使用特殊字符、空格、连续的下划线

注: 如有可能,避免定义由下划线,struct,enum,或者command开始的标识符。虽然这些是有效的标识符,当你下载技术包时可能导致出现错误。在基础系统和在技术包 中命令词语,参数或数据类型以这些字符开始。

2.2关键字

语法关键字区分大小写,总是大写字母

例如:

  •  标准的逻辑运算操作:       AND,OR,NOT…  
  • 标准的数据类型关键字:    BOOL,INT,REAL…  
  • 程序和功能块的关键字:    FUNCTION,FUNCTION_BLOCK,PROGRAM  
  • 结构体数据相关的关键字:TYPE,STRUCT

注:关键字是不可以声明做变量名的。

2.3注释

  • 线注释:“ //  ” ,单行且放在行尾。
  • 块注释:由“(*”开始,由“*)”结束,可以多行。
  • 注释可以放在行首,行尾,也可以放在程序语句中间,但是不能放在字符串中间。
  • 注释不允许嵌套。

二、数据类型

2.1 基本数据类型

数据类型有整数, 浮点数, 位和位组, 时间和日期值 和字符串

2.1.1基本数据类型的数据范围和大小

数据类型

数据范围

数据大小

类型类型名描述

最小值

最大值

位和位组数据类型

BOOL

False

True

1bit

BYTE

字节

0

255

8bit

WORD

0

65535

16bit

DWORD

双字

0

4294967295

32bit

整型

SINT

短整型

-127

127

8bit

USINT

无符号短整型0255

8bit

INT

整型

-32768

32767

16bit

UINT

无符号整型

0

65535

16bit

DINT

双整型

-2147483648

2147483647

32bit

UDINT

无符号双整型0

4294967295

32bit

LINT

长整型

-2^63

2^63-1

64bit

ULINT

无符号长整型02^64-1

64bit

日期和时间表示

TIME_OF_DAY

时间

TOD#00:00:00

TOD#23:59:59

32bit

DATE

日期

D#1970-01-01

 D#2106-02-07

32bit

DATE_AND_TIME

日期和时间

DT#1970-01-01- 00:00:00

DT#2106-02-07- 06:28:15

32bit

时间数据类型

TIME

时间

T#0s

T#49D17H2M47S295MS

32bit

浮点数类型

REAL

实数

-3.4*1038

3.4*1038

32bit

LREAL

长实数

-1.7*10308

1.7*10308

64bit

字符串数据类型

STRING

字符串

ASCII码的字符串数据类型,一个字符占一个BYTE位。最 多可以有255个字符。

WSTRING

Unicode编码的字符串,一般情况下一个字符占两个BYTE 位。它本身对字符串长度没有限制。

注:声明变量时需注意不要超过数据类型的大小。

2.1.2基本数据类型的表示

语法:<类型>#<数值>

<类型>指定所需的数据类型;可能 BOOL, SINT, USINT, BYTE, INT, UINT,
WORD, DINT, UDINT, DWORD, REAL, LREAL 该类型必须是书面的大写字母。
举例:
2#0101,10#123,16#FF,BOOL#TURE,BYTE#12,INT#255,T#12h23m30s90ms,
D#2023-06-16

整型
  • 允许十进制、十六进制(16#)、八进制(8#) 和 二进制(2#) 表示。
  • 可用下划线(_) 作单元分隔
十进制十六进制八进制二进制
-3276816#80018#777772#1000_0000_0000_0001
123        16#7b8#1732#1111011
浮点数(实数) 表示
  •  十进制小数或指数表示 
十进制指数表示
12301.23e3
0.33333.333e-1
时间数据类型
  •  在文字前加TIME#, t# 或 T#
  • 允许溢出(例如25 小时)
  • 使用d 表示天, h 表示小时, m 表示分, s 表示秒和 ms 表示毫 秒
  • 可使用下划线(_) 作单元分隔
  • T#2d_26h_4m_12s_123ms
日期和时间数据类型
  • 用DATE#或D# 表示日期
  • 用TIME_OF_DAY# 或 TOD# 表示一天中的时间
  • 用DATE_AND_TIME# 或 DT# 表示日期和时间
  • 日期:D#1998-12-07 表示7th July 1998
  • 一天中的时间: TOD#12:00:00.123
  • 日期和时间: DT#1998-12-07-12:00:00.123
字符串
  • ''引括字符
  • $插到特殊字符前(换行$L ,制表$T等)
  • 字符串表示: 'this is a line feed character $L'
  • 空字符串: ''
位和位组
  • TRUE 或 1
  • FALSE 或 0
  • 用十进制,十六进制, 八进制或二进制表示
  • 45054、16#AFFE、2#1010_1111_1111_1110

2.2 用户定义的数据类型(DUT)

  • 根据基本数据类型或其它用户定义的数据类型建立自己的数据类型
  • 可通过关键字TYPE…END_TYPE来声明结构体数据、共用体数据和一些自定义数据。

TwinCAT3提供默认的文件夹分组,如下图所示:

  • DUTs :用户自定义数据类型
  • GVLs:全局变量
  • POUs:程序、功能块、函数
  • VISUs:可视化界面

声明步骤为:

  •  右击DUTs,
  • 点击Add,
  • 选择DUT出现Creat type对话框。  
  • 选择相应的数据结构进行编程。

2.2.1 结构体数据(Struct)

对于同一组的变量,可以用结构体数据类型进行定义,每个元素的数据类型可以不同,结构体可以做成需要的数据类型,并且结构体数据可以方便进行数据的修改,以方便日后的使用。

1. 声明方式
TYPE 标识符 :
 STRUCT
  变量名1 : 数据类型 [:= 初值1];
  变量名2 : 数据类型 [:= 初值2];
       ...
  变量名n : 数据类型 [:= 初值n];
 END_STRUCT
END_TYPE
2. 调用
  • 调用前需要实例化 

  • 实例化语法:变量名 : 结构体名;

3.例子

结构体S1定义: 

TYPE S1:
  STRUCT
    Var1 : INT;
    Var2 : WORD := 16#AFA1;
    Var3 : BYTE := 16#FF;
  END_STRUCT
END_TYPE

MAIN函数 

VAR
 myS1 : S1;
END_VAR

myS1.Var1 := -4;
myS1.Var3 := 16#22;

 调试结果:

(1)初始状态

 (2)执行第一条语句

(3)执行第二条语句 

2.2.2 枚举变量(Enumeration)

枚举变量是多个有固定数值的一类变量的集合。

当程序中有多个固定值输入,若将其声明为枚举变量后,则可以使用助记词帮助了解这些固定值输入的用处,这比看数字清楚很多。且在数据修改时,只需在声明枚举变量处改动即可对于多处使用到的数据进行修改。

1. 声明方式:
TYPE 枚举名 :
(
  成员名1 [:= 初值1],
  成员名2 [:= 初值2],
      ...
  成员名n [:= 初值n]
);
END_TYPE

注:如果没有设置初值,各成员的初值默认为前一个成员的初值加1,第一个成员默认为0。

2. 调用
  • 调用前需要实例化 

  • 实例化语法:变量名 : 枚举名;

3.例子

注:枚举变量的创建都会自动加上属性编译:{attribute 'qualified_only'} 其含义是为了区分各个枚举变量的成员名之间的重名问题,因此调用枚举变量的成员时需要在成员名前加上枚举变量名。

 调试结果:

(1)初始状态 

 

(2)执行第一条语句

(3)执行所有语句

2.2.3 别名(Alias)

用别名(Alias)来为变量、函数等创建一个新的名称。这可以使代码更易读,也可以用于创建引用或者简化一些表达式。

1. 声明方式:
TYPE
  别名 : 基本数据类型[:= initialization ] ;
END_TYPE

或:

TYPE
  别名 : 用户定义数据类型[:= initialization ] ;
END_TYPE
2. 调用
  • 调用前需要实例化 

  • 实例化语法:变量名 : 别名;

3.例子
TYPE
  R1 : REAL;
  R2 : R1;  //可以用派生的数据类型标识符声明变量
END_TYPE 

2.2.4 共用体(Union)

共用体中的多个数据共用一段内存地址,一旦其中一个变量数值发生了变化,其他变量会一致变化。

 1、声明方式:
TYPE 共用体名 :
UNION
  变量声明
END_UNION
END_TYPE
2. 调用
  • 调用前需要实例化 

  • 实例化语法:变量名 : 共用体名;

3.例子

调试结果: 

 注:sVar和aVar变量共用一段内存地址,在使用过程中,这段地址中的字符串可以以字符串方式访问又可以字符数组方式访问,简化了对数据的处理方式并且节省内存。

三、变量声明

  • 具有基本类型或用户定义类型的局部和全局变量
  • 用一个VAR..END_VAR 结构框架声明变量
  • 同样数据类型的变量用逗号列出
  • 运行过程中变量是允许变化
  • 变量的地址一般是不需要知道的
  • 如果指定初始值,变量值默认为0,时间数据类型和枚举数据类型除外。

3.1 基本数据类型

1、声明方式
变量名 : 数据类型 [:= 初值];
2、例子
VAR
  a : BOOL;
  b,c : INT := 1;
  d : STRING := ‘this isastring‘;;
  e : REAL := 1.1;
  f,g : REAL;
END_VAR

3.2 数组

1、一维数组声明方式:
变量名 : ARRAY[M..N] OF 数据类型[:= 初值];

阵列限制[M..N]

  • 声明了索引值的最小值M和最大值N
  • 阵列限制必须用两个句号隔开
  • 全部的索引声明须在方括号中
  • 索引可以为一个数据类型DINT(或转化为DINT)的整数值
2、二维数组声明方式
变量名 : ARRAY[M..N] OF 一维数组变量名;
3、避免数组超限

使 用数组变量编程时,可以使用TwinCAT3提供的Checkbounds 这个功能块来防止 访问数组变量时,索引值超出数组长度的情况。功能块的使用非常简单,只要按 下述方式添加到程序中即可:

出现以下函数即可,无需调用,它会自动识别是否有数组索引超限,如果有超限的将数组索引指向数组最后一位。 

 

以下列循环为例,数组a索引范围为[0,2],但循环存在a[3]。 

运行结果如下:

当i = 3时,实际运行a[2]=i; 

4、例子

VAR
  a : ARRAY[0..10] OF BOOL;
  b : ARRAY[1..10] OF INT := 1, 2, 2, 4,5, 6, 7, 8, 9,10;
  c : ARRAY[0..100] OF DWORD;
  d : ARRAY[0..1] OF DATE;
  e : ARRAY[0..17] OF REAL;
END_VAR

a[1]:=1;
b[2]:=100;
VAR
  a : ARRAY[1..3] OF INT;
  b : ARRAY[1..4] OF a;
END_VAR

b[4][3]:=9;

3.3 变量作用域

关键词意义声明
VAR暂时或静态变量

程序

功能

功能块

表达式

VAR_GLOBAL全局变量
VAR_IN_OUT

输入/输出变量

POU直接访问变量,也可直接修改。

功能

功能块

表达式

VAR_INPUT

输入变量

数值 是外部赋予,不能在POU里 面改变这个数值。

功能

功能块

表达式

VAR-OUTPUT

输出变量

数值是从功能块传递的。

功能块
VAR_TEMP临时变量

程序

功能块

3.3.1 局部变量

  •  变量在一个POU(程序,功能块或函数)中的变量声明区域VAR声明
  • 只能在这个POU中访问。
  •  声明在在程序功能块(FB)中相应关键字区域。
    • VAR...END_VAR中声明本地变量
    • VAR_INPUT...END_VAR中声明输入型变量。
    • VAR_OUTPUT...END_VAR中声明输出型变量。
    • VAR_IN_OUT...END_VAR中声明输入输出型变量,这里的变量即是输入也是输出。

例:

VAR
  I AT%I* : BYTE;
END_VAR

VAR_INPUT
  a : BYTE;
END_VAR

VAR_OUTPUT
  b : INT;
END_VAR

VAR_IN_OUT
  c : BYTE;
END_VAR

3.3.2 全局变量

  •  变量在一个资源(PLC 运行核-runtime)中定义说明
  • 每个POU均可访问
1、声明方式

全局变量在TwinCAT3中变量声明的方式如下:

  •  在GVLs上右击
  • 点击Add
  • 选择Global Variable List
  • 在这里个文件的 VAR_GLOBAL 中声明对应的全局变量

2、例子:
VAR_GLOBAL
  a : BOOL;
  b : INT;
  c : BYTE;
END_VAR

注:在 TC3.1.4020 版本开始,全局变量的创建都会自动加上属性编译:{attribute 'qualified_only'} 其含义是为了区分全局变量与各局部变量重名的问题,因此现在调用全局变量都 需要在变量名前加上全局变量的命名空间。

例如:GVL.a,GVL.b,GVL.c,但如果 感觉这种方式不习惯或者麻烦,也可以把属性编译行删除,就可以回到以前的直 接调用的方式了。 

3.4 变量属性

 3.4.1 常数

常量在系统初始化完成后,便只能进行读操作,不能进行赋值。

1、声明方式

常量的声明方式是在变量声明区域关键字后加相应的关键字CONSTANT

VAR CONSTANT
  标识符 : 数据类型 := 初值;
END_VAR

注:常量必须有初始值。

2、例子
VAR CONSTANT
  PI : REAL:=3.1415926;
END_VAR

3.4.2 断电保持型数据

断电保持型变量是将变量值保存到本地硬盘中,设备重新上电后自动进行读取。

1、声明方式1

断电保持型数据的声明方式是在变量声明区域关键字后加相应的关键字PERSISTENT

VAR PERSISTENT
  标识符 : 数据类型 [:= 初值];
END_VAR
2、例子
VAR PERSISTENT
  iount : INT;
END_VAR

注:定义PERSISTENT 类型变量需要配合UPS才可以保存变量,因为此类变量只 有当PLC停止的时候才会进行保存,不然断电重启还是会丢失。

3、声明方式2

调用Tc2_Utilities.LIB 库文件中的写掉电保持数据功能块FB_WritePersistentData。

3.4.3 指定内存地址

具有固定地址的变量

1、自动分配内存地址
VAR
  变量名1 : AT%I* 数据类型;  //输入
  变量名2 : AT%I* 数据类型;  //输入
  变量名3 : AT%Q* 数据类型;  //输出
  变量名4 : AT%Q* 数据类型;  //输出
END_VAR

输入输出变量通过“AT%I(Q)*”来进行声明。

  •  AT% 是关键字
  • I   表示输入
  • Q 表示输出
  • * 表示自动分配一个内存地址给这个变量。也可以指定一个内存地址给这个变量。

注:只有加上“AT%I(Q)*”,TwinCAT3中的Instance中才能识别到!

2、指定内存地址

语法: %<存储器区前缀><长度前缀><数字1>.<数字2>

  • %:表示操作数。
  • 存储器区前缀: 表示该操作数的存储位置区域:
    • I :输入区域, 物理输入;
    • Q:输出区域,物理输出;
    • M:内存区域。
  • 长度前缀: 表示操作数的长度
    • X: Bit,一位,X类型变量类型:BOOL
    • B: Byte,一个字节,B类型变量类型:BYTE,SINT,USINT,BOOL
    • W: Word,一个字,W类型变量类型:WORD,INT,UINT
    • D: Double Word,两个字,D类型变量类型:DWORD,DINT,UDINT、REAL
  • 数字1:变量对应内存的偏移地址
  • 数字2:作为BOOL或者word等类型时,偏移地址后的第几位

例如:%IX0.0表示输入存储区域的二进制数第0个字节第0个bit位。

四、函数,功能块和程序

函数(FC)是指无静态数据的编码块。当退出功能时所有的本地变量丢失数值,下次再调用功能时再重新启动。

功能块(FB)是指带静态数据的编码块。FB 有内存,所以在用户程序中可以随时访问输出参数。本地变量在调用之间保持原值

程序与FB类似,但是没有参数。然而,却可以指定执行级别和任务。

FC 和FB有着可以重新使用的优势。

4.1 函数(FC)

4.1.1 函数声明

FUNCTION 函数名 : 数据类型
  (* 变量声明 *)
  VAR_INPUT
    变量声明
  END_VAR

  (* ST编程中的代码体 *)
  代码
END_FUNCTION  
  • 如果函数没有返回值,则输入VOID为数据类型。 
  • 内部数据不存储,所有的本地变量(VAR ... END_VAR)在FC中都是临时的,当FC结束时,它们的数值将丢失。下次调用FC时,将重新启动。
  • 几个输入值
  • 一个输出值
  • 用户定义的函数可以用各种语言编辑代码(除了SFC)
  • 函数名必须和返回值的名称相同

例:

FUNCTION Average : REAL   //返回值的数据类型
  VAR_INPUT
    IN1, IN2 : REAL ;
  END_VAR

   Average:= (IN1 + IN2)/2; //返回值名 = 函数名
END_FUNCTION  

4.1.2 函数的调用

变量名 := 函数名(输入参数1 := 值1,输入参数2 := 值2,...,输入参数n := 值n,
                输入输出参数1 := 值1,输入输出参数2 := 值2,...,输入输出参数n := 值n);

注:没有输出参数 

4.2 功能块

  • 设立输入, 输出和内部变量
  • 运算法则建立新的输出和内部变量
  • 参数被保持到下次执行(在存储器中),关闭FB时,静态数据(VAR ... END_VAR)保持原值
  • 关闭FB时,临时变量(VAR_TEMP ... END_VAR)数值丢失
  • 功能块例程是一个结构, 包含所有输入, 输出和内部变量
  • 一个功能块FB 允许建立多个实例
  • 在FB 的外部只有输入, 输出和输入/输出变量传递参数
  • 在其它FB或程序中, 以不同的编程语言使用FB调用
  • 一个FB 例程在调用的FB/程序中是一个变量或全局变量
  • FB例程可以是对其它FB/程序的输入变量

4.2.1 功能块声明

FUNCTION_BLOCK 功能块名
  (* 输入 *)
  VAR_INPUT
    变量声明
  END_VAR

  (* 输出 *)
  VAR_OUPUT
    变量声明
  END_VAR

  (* ST编程中的代码体 *)
  代码
END_FUNCTION_BLOCK

例:

FUNCTION_BLOCK Counter
 VAR_INPUT
 Mode : INT; (* 0 = 重置,1 = 计数*)
 END_VAR

 VAR_OUPUT
 Out :  INT; (*实际计数器值*)
 END_VAR

 IF Mode = 0 THEN
    Out:= 0;
 ELSIF Mode = 1  THEN
    Out:=Out+ 1;
 END_IF;
END_FUNCTION_BLOCK

4.2.2 功能块的调用

在调用一个功能块(FB)之前,你必须声明一个实例

实例名 : 功能块名;

调用功能块:

实例名(输入参数1 := 值1,输入参数2 := 值2,...,输入参数n := 值n,
       输入输出参数1 := 值1,输入输出参数2 := 值2,...,输入输出参数n := 值n,
       输出参数1 => 值1,输出参数2 => 值2,...,输出参数n => 值n);
//调用功能块后,可以读出FB的输出参数
变量名 := 实例名.输出变量;
  •  使用=>运算符来指定输出参数
  • 变量名为上述声明的实例

4.2.3 TwinCAT快捷键调用功能块

(1)首先在变量声明区域,声明一个功能块实例。

(2)然后在程序编写区域按键盘的 F2 键选择声明好的实例,会自动调出相应的功能块。将所需参数填写入相应位 置,就完成了功能块的调用。

下面是调用功能块的例子: 

  • fb_TON1 便是功能块TON的实例
  • ()中的内容是输入输出参数,根据自己的需要进行读写

对功能块中的单独项可以通过下面方式访问:

4.3、函数和功能块的比较

4.3.1 功能块案例

FUNCTION_BLOCK Circle1
    (* 常数声明 *)
    VAR CONSTANT
        PI : LREAL := 3.1415;
    END_VAR
    (* 输入参数 *)
    VAR_INPUT
        Radius : LREAL;
    END_VAR
    (* 输入输出参数 *)
    VAR_IN_OUT
        Circumference : LREAL;
    END_VAR
    (* 输出参数 *)
    VAR_OUTPUT
        Area : LREAL;
    END_VAR
    (* 局部变量、静态 *)
    VAR
        Counter : DINT; //每次调用,变量保留其值
    END_VAR

    Counter := Counter + 1;
    Circumference := 2 * PI * Radius;
    Circle2 := PI * Radius**2;  //函数返回值
END_FUNCTION_BLOCK

PROGRAM CircleCalc1
    VAR
        myCircle1 : Circle1; //声明Circle1功能块实例
        myArea1, myArea2 : LREAL;
        myCircf : LREAL;
    END_VAR

    myCircle1(Radius := 3,Circumference := myCircf, Area => myArea1);  //功能块调用
    myArea2 := myCircle1.Area;
    //myCircf的值为18869
    //myArea1的值为28274
    //myArea2的值为28274
END_PROGRAM

4.3.2 函数案例

FUNCTION Circle2 : LREAL
    (* 常数声明 *)
    VAR CONSTANT
        PI : LREAL := 3.1415;
    END_VAR
    (* 输入参数 *)
    VAR_INPUT
        Radius : LREAL;
    END_VAR
    (* 输入输出参数 *)
    VAR_IN_OUT
        Circumference : LREAL;
    END_VAR
    (* 输出参数 *)
    VAR_OUTPUT
        Area : LREAL;
    END_VAR
    (* 局部变量、静态 *)
    VAR
        Counter : DINT; //每次调用,变量会初始化为0
    END_VAR

    Counter := Counter + 1;
    Circumference := 2 * PI * Radius;
    Circle2 := PI * Radius**2;  //函数返回值
END_FUNCTION

PROGRAM CircleCalc2
    VAR
        myArea : LREAL;
        myCircf : LREAL;
    END_VAR

    myArea := Circle2(Radius := 3,Circumference := myCircf);  //函数调用

    //myCircf的值为18869
    //myArea的值为28274
END_PROGRAM

4.3.3 对比

功能块FB函数FC
没有返回值返回值的数据类型必须在名称后说明。如果没有返回值,数据类型为VOID
可以使用In/out参数来读写转移变量
可以使用输出参数从FB回送数值不允许输出参数
本地变量是静态的,在FB调用中保留数值计数器本地变量增加;当FB结束时保留其数值。因此每次调用FB时变量增加。本地变量是临时的当功能结束后数值丢失。虽然计数器本地变量增加,当FC退出时数值丢失。下次调用FC时变量重新恢复(例子中变为0)
在语句部分,结果(回送值)被指定为输出 或in/out参数在语句部分,结果(回送值)被指定为功 能名称(除了特别指定VOID数据类型之 外)
调用功能块前,需要声明FB的一 个实例。(声明一个变量,指定FB名称为它 的数据类型。)
读出FB的输出参数读出FC的返回值

4.4 程序

  • 程序可以有输入, 输出, 局部变量和算法的程序代码部分
  • 不同于FB: 程序没有例程
  • 程序没有存储器
  • 在程序中使用各种语言
  • 程序由任务来调用(TwinCAT: 可由其它程序调用)

 4.4.1 程序声明

PROGRAM 程序名
  VAR
    变量声明
  END_VAR
 
  代码
END_PROGRAM

例子:

PROGRAM Main
  VAR
    counter_1 : Counter; (*  FB 计数器实例 *)
    actCount   : INT;
  END_VAR
 
  IF bfirstCycle
  THEN
    counter_1(Mode := 0);(* callFB带复位模式 *)
  ELSE
    counter_1(Mode := 1);(* callFB带计数模式*)
  END_IF

  actCount:=counter_1.Out; (*使用counter_1*的输出变量*)
END_PROGRAM

五、语法

5.1表达式

 5.1.1 操作符

5.1.2 赋值

赋值指令用于变量赋值,也就是赋值关键字的左边是变量,右侧为要赋的值,通过赋值关键字进行赋值。

其中的赋值关键字包含三种:“:=”、“S=”、“R=”。 

  • “:=”为一般赋值,右值直接赋给左值,左值和右值相等。
  • “S=”为置位赋值,表示如果右值为TRUE,左值变量变为TRUE(置位), 直到调用R=命令来初始化
  • “R=”为复位赋值,表示如果右值为TRUE,左值变量变为FALSE(复位)。用于复位S=指令置位的变量。
变量名:= 值;

例如:a S= b; 一旦b为 TRUE后,a会保持 TRUE, 即使b 变为 FALSE后。 

5.1.3 位访问

变量1     := 变量2.位;
变量1.位  := 变量2;
变量1     := 变量2[位];
变量1[位] := 变量2;

 注:访问I/O变量或者系统变量的二进制数字可以被其他任务干扰,所以不能保证一致性

例:

A[i] := B; //数组A
A[i+1] := SIN(SQRT(A[i+3]));
C :=timer.Q; (* timer 是 FB TOF 的一个实例 *)
D := E/F + COS(A[i+1]);
bFlag:= X AND Y OR Z;

5.2 条件选择

5.2.1 IF条件语句

IF条件语句,在布尔表达式的值为TRUE时执行(执行语句)。布尔表达式可以是布尔类型的变量(bVar..),可以是比较判断的值(a>b),功能块的值的判断(LEFT(STR:= strVar, SIZE:=7) = 'TwinCAT')等等。

1、声明方式 
IF <布尔表达式> THEN
     <执行语句> 
ELSIF (布尔表达式> THEN 
     <执行语句> 
ELSE
     <执行语句> 
END_IF
2、例子
 IF temp<20 THEN 
heating_on := TRUE;
 ELSE 
heating_on := FALSE;
 END_IF;
 (*温度低于20度,加热器打开,否则关闭。*)

5.2.2 CASE选择语句

CASE选择语句根据选择条件中的值,执行相应执行语句。

1、声明方式 
CASE <整数表达式> OF
 <整数选择值1> : <语句>
 <整数选择值2> : <语句>
 ...
 <整数选择值n> : <语句>
 ELSE
 <语句>
END_CASE;
2、例子
CASE INT1 OF
 1: BOOL1 := TRUE;
    BOOL2 := FALSE;
 2: BOOL1 := FALSE;
    BOOL2 := TRUE;
 ELSE
    BOOL1 := FALSE;
    BOOL2 := FALSE;
END_CASE;

5.3 循环语句

5.3.1 FOR循环语句

 循环次数已知时,你可以使用FOR语句。如果循环通过次数未知,WHILE 或REPEAT语句更适合。

1、声明方式
FOR <变量名>:=<起始值> TO <终值表达式> BY <增量表达式> DO
  <语句>
END_FOR;
  • 可以省略BY(增量)说明。如果没有指定增量,那么默认为+1。
  • 起始值,结束值和增量为表达式时,在开始FOR语句时会估算表达式。 
  • 如果起始值和结束值为 DINT 数据类型,数值(结束值—起始值)必须小于双整数的最 大值的范围,即小于2^31-1
2、例子
FOR i:=1 TO 12 BY 2 DO 
   Feld:=i*2
END_FOR

5.3.2 WHILE 循环语句

当循环通过次数未知时,可以使用WHILE语句。如果次数已知,FOR 语句更为适合。

1、声明方式
 WHILE <布尔表达式> DO
 <语句>
 END_WHILE;
  • 每次在执行语句部分之前估算迭代条件
  • 如果值为TRUE,执行语句部分
  • 如果值为FALSE, 结束WHILE语句 
2、例子
i:=0; 
WHILE i<100 DO
   Feld:=i*2; 
   i:=i+1; 
END_WHILE

5.3.3 REPEAT 循环语句

当循环通过次数未知时,可以使用REPEAT语句。如果次数已知,FOR 语句更为适合。

1、声明方式
 REPEAT
  <语句>
 UNTIL <布尔表达式>
 END_REPEAT;
  • 重复执行 REPEAT到UNTIL之间顺序的语句 
  • 每次在执行语句部分之后估算迭代条件,这意味着语句部分至少要执行 1 次
  • 如果值为FALSE,再次执行语句部分
  • 如果值为TRUE, 结束REPEAT语句的执行
2、例子
i:=0; 
REPEAT 
  Feld:=i*2; 
  i:=i+1; 
  UNTIL i>100 
END_REPEAT

5.4 跳转语句

5.4.1 EXIT语句

EXIT 语句被用作在任何点退出一个循环(FOR, WHILE 或 REPEAT 循环),不考虑结束条 件是否为TRUE或FALSE。 

例:

FOR i := 0 TO 9 DO                //FOR循环开始
    IF (Input[i] = TRUE) THEN     //条件判断
      EXIT;                       //条件若成立,执行EXIT语句,退出FOR循环控制语句。
    END_IF;
END_FOR;

 5.4.2 CONTINUE

CONTINUE语句用于提前结束本轮循环,并重新开始下一轮循环。 

5.4.3 RETURN语句

RETURN 语句引起结束现在运行(程序,功能,功能块)的POU。

例:

Index:=  1;  
FOR Index  :=  1 to  51 BY  2 DO  
  IF Index=4 THEN  
    RETURN;  
  END_IF;  
END_FOR;  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1976230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三十七、MyBatis-Plus(3)

&#x1f33b;&#x1f33b; 目录 一、CRUD 扩展 (2)1.1 Select1.2 分页查询1.3 Delete1.3.1 物理删除1.3.2 逻辑删除 二、性能分析插件三、条件构造器四、代码自动生成器 一、CRUD 扩展 (2) 1.1 Select 查询所有&#xff1a; /* * 查询 * */Test //查询全部 public void sele…

PCB设计经验——布线原则

1.连线精简——避免直角布线 导线也应看作一种元器件&#xff0c;有自己的电阻&#xff0c;电感&#xff0c;电容 PCB走线在直角转弯的地方&#xff0c;信号前后部分相互影响&#xff0c;导致分布电容增加&#xff0c;对信号上升沿和下降沿有延缓影响。从阻抗的角度来说&#…

鸿蒙媒体开发【相机数据采集保存】拍照和图片

相机数据采集保存 介绍 本示例主要展示了相机的相关功能 接口实现相机的预览拍照功能。 效果预览 使用说明 弹出是否允许“CameraSample”使用相机&#xff1f;点击“允许”弹出是否允许“CameraSample”使用麦克风&#xff1f;点击“允许”进入预览界面&#xff0c;预览正…

快递点“内鬼”才是倒卖我们个人信息的源头

下面是一个真实的案例来分析一下我们的信息是怎么被倒卖出去的。以次来给大家敲响警钟&#xff0c;不要相信所谓的退货退款类的诈骗。【所有涉及到金钱的都是诈骗&#xff0c;获取你信息也很容易&#xff0c;所以不要轻信诈骗谎言】 01-盗取快递信息过程 内鬼与骗子勾结&…

深度学习(1)--机器学习、人工智能、深度学习的关系

1956 年提出 AI 概念&#xff0c;短短3年后&#xff08;1959&#xff09; Arthur Samuel 就提出了机器学习的概念&#xff1a; Field of study that gives computers the ability to learn without being explicitly programmed. 机器学习研究和构建的是一种特殊算法&#xff0…

Mindspore框架DCGAN模型实现漫画头像生成|(二)DCGAN模型构建

Mindspore框架DCGAN模型实现漫画头像生成 Mindspore框架DCGAN模型实现漫画头像生成|&#xff08;一&#xff09;漫画头像数据集准备Mindspore框架DCGAN模型实现漫画头像生成|&#xff08;二&#xff09;DCGAN模型构建Mindspore框架DCGAN模型实现漫画头像生成|&#xff08;三&a…

广州市广州城市信息模型(CIM)白皮书学习

一级标题 二级标题 框架 四级标题 五级标题 六级标题 CIM平台定义 以建筑信息模型(BIM)、地理信息系统(GIS)、物联网(IoT)等技术为基础&#xff0c;整合城市地上地下、室内室外、历史现状未来多维多尺度信息模型数据和城市感知数据&#xff0c;构建起三维数字空间的城市…

主持人大赛活动流程和规则

比赛内容&#xff1a; ①命题主持三分钟 选手抽签获得一命题主持内容&#xff0c;思考三十秒后开始主持 ②模拟主持两分钟 选手提前自己准备好&#xff0c;模拟主持一段电视或广播节目。 要求创意新颖、声情并茂。 ③即兴演讲两分钟 选手现场抽题。抽到一个话题&#xff0c;思…

算法021:山脉数组的峰顶索引

山脉数组的峰顶索引. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/peak-index-in-a-mountain-array/ 这个题&#xff0c;看似好像不是递增或者递减数组&#xff…

【网络安全入门】学习网络安全必须知道的77个网络基础知识

1、TCP/IP 协议的四层模型&#xff08;网络接口层、网络层、传输层、应用层&#xff09; TCP/IP 协议是互联网通信的基础&#xff0c;四层模型中&#xff0c;网络接口层负责与物理网络的连接&#xff1b;网络层主要处理 IP 数据包的路由和转发&#xff1b;传输层提供端到端的可…

电路原理分析

文章目录 0 基础符号说明电容电感电阻U/IC二极管三极管变压器杂合元件IGBT电机运放开关TPJ高组态电阻上拉电阻可靠高电平提高驱动能力阻值选择下拉电阻可靠低电平晶振压电效应晶振原理实物电荷泵电路防倒灌电路0 基础符号说明 电容 电容 C Electrolytic capacitor 电解电容 E…

内网穿透--LCX端口转发实验

实验背景 通过公司带有防火墙功能的路由器接入互联网&#xff0c;然后由于私网IP的缘故&#xff0c;公网无法直接访问内部主机&#xff0c;通过端口转发&#xff0c;穿透访问内网主机服务。 实验设备 1.路由器一台&#xff0c;实现内部 DHCP 分配和边界 NAT 2.外网 window20…

Java语言程序设计——篇十一(3)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; 欢迎大家&#xff1a;这里是我的学习笔记、总结知识的地方&#xff0c;喜欢的话请三连&#xff0c;有问题可以私信&#x1f333;&#x1f333;&…

JavaFX布局-ButtonBar

JavaFX布局-ButtonBar 常用属性buttonOrderpaddingbuttonMinWidth 实现方式Java实现fxml实现 一个特殊的容器&#xff0c;用于创建一组按钮&#xff0c;水平排列按钮太多&#xff0c;会被遮住&#xff0c;不会自动产生滚动条 常用属性 buttonOrder 预制顺序 buttonBar.setBut…

别再盲目推广了!Xinstall助你开启App线下推广新篇章

在这个数字化飞速发展的时代&#xff0c;App已经成为我们生活中不可或缺的一部分。然而&#xff0c;App市场的竞争也日益激烈&#xff0c;如何让你的App在众多竞争者中脱颖而出&#xff0c;成为每个推广者必须面对的问题。今天&#xff0c;就让我们一起探讨一下App线下推广的痛…

【2024】Datawhale AI夏令营 Task4笔记——vllm加速方式修改及llm推理参数调整上分

【2024】Datawhale AI夏令营 Task4笔记——vllm加速方式修改及llm推理参数调整上分 本文承接文章【2024】Datawhale AI夏令营 Task3笔记——Baseline2部分代码解读及初步上分思路&#xff0c;对其中vllm加速方式进行修改&#xff0c;推理速度获得了极大提升。另外&#xff0c;…

【JAVA入门】Day17 - GUI

【JAVA入门】Day17 - GUI 文章目录 【JAVA入门】Day17 - GUI一、组件二、事件 GUI 即图形化界面。 一、组件 一个 Java 的图形化界面项目主要用到了下面几种组件。 Java 中最外层的窗体叫做 JFrame。Java 中最上层的菜单叫做 JMenuBar。Java 中管理文字和图片的容器叫做 JLab…

快速体验LLaMA3模型微调(超算互联网平台国产异构加速卡DCU)

序言 本文以 LLaMA-Factory 为例&#xff0c;在超算互联网平台SCNet上使用异构加速卡AI 显存64GB PCIE&#xff0c;对 Llama3-8B-Instruct 模型进行 LoRA 微调、推理和合并。 超算互联网平台 异构加速卡AI 显存64GB PCIE 一、参考资料 github仓库代码&#xff1a;LLaMA-Fac…

C#中的Winform基础

program 每个Windows应用程序都会有一个Program类——程序入口点 [STAThread] ----指示应用程序的COM线程模型是单线程单元&#xff08;如果无此特性&#xff0c;无法工作&#xff09; static voidMain() —— 入口 System.Windows.Forms.Application类提供一系列静态方法和…

【C++】一堆数组案例 元素逆置

所谓元素逆置就是把一堆数组的元素顺序反过来 例如一堆数组的为 1&#xff0c;2&#xff0c;3&#xff0c;4 那么它的逆置为 4&#xff0c;3&#xff0c;2&#xff0c;1 逆置过程运用赋值存储的思想&#xff0c;先把第一个数组存贮到一个变量中&#xff0c;然后把末尾数组…