PLC编程系统42
用的功能的子程序,有
存储区
中型 PLC 的 OB、FB、FC 的总数之和最多1024个,空间之和最大 128KBytes,单块最大空间64KBytes,OB+FB+FC 大小≤CPU 程序空间大小功能(FC)
用户编写的包含经常使
用的功能的子程序,无
存储区
小型 PLC 最多支持 255 个FC
中型 PLC 的 OB、FB、FC 的总数之和最多1024个,空间之和最大 128KBytes,单块最大空间64KBytes,OB+FB+FC 大小≤CPU 程序空间大小背景数据块
(DI)
调用 FB 时用于传递参
数的数据块
小型 PLC 不支持 DI
中型 PLC 中 DI 和 DB 块总共最多254 个,DI 和DB 在 CPU 中的总大小≤118KBytes,单块最大空间64KBytes;支持掉电保持功能(用户可选);共享数据块
(DB)
存储用户数据的数据区
域,供所有的块共享,
即为 V 存储空间
小型 PLC 不支持 DB
中型 PLC 中 DI 和 DB 块总共最多254 个,DI 和DB 在 CPU 中的总大小≤118KBytes,单块最大空间64KBytes;支持掉电保持功能(用户可选);SFC 保密库 CT LIB1 和 CT
LIB2 的接口。
2 个,若想使用 CT LIB1 或CT LIB2,需在程序中调用此 POU。
<备注> 各个块的描述详见后续章节。
5.3.1 OB 组织块
组织块(OB)表示操作系统和用户程序之间的接口。组织块由操作系统调用,控制循环中断驱动的程序执行、PLC 启动特性和错误处理。可以对组织块进行编程来确定CPU 特性。其中,程序的主体 OB1 是放置控制应用程序指令的位置,主程序中的指令按顺序执行,每次CPU扫描周期时执行一次。
组织块的优先级
组织块确定单个程序段执行的顺序(启动事件)。一个 OB 调用可以中断另一个OB的执行。哪个 OB 允许中断另一个 OB 取决于其优先级。高优先级的 OB 可以中断优先级低的OB。中断事件
启动事件触发 OB 调用称为中断。您可以通过中断指令赋给 OB 中断事件号,然后根据组内优先级执行中断。中断优先级列表请参考附录 E 中断事件优先级列表。例如,将中断事件号 10 赋给 OB3,STL 程序如下:
LD SM 0.0
ATCH OB3, 10
ENI
5.3.2 FB 功能块(CTH300 系列 PLC 适用)
FB 功能块是拥有自己的存储区(背景数据块)的块,每次调用功能块时需要提供各种类型的数据给功能块,功能块也要返回变量给调用它的块。这些数据以静态变量(STAT)的形式存放在指定的背景数据块(DI),临时变量 TEMP 存储在局部数据堆栈中。调用 FB 时,必须指定 DI 的编号。在编译 FB 时,自动生成背景数据块中的数据。一个功能块可以有多个背景数据块,用于不同的被控对象。
MagicWorks PLC 编程软件用户手册
43
可以在 FB 的变量声明表中给形参赋初值。如果调用块时没有提供实参,将使用上一次存储在DI 中的参数。局部符号表
数据类型
1、支持的参数类型
可以在变量表中编辑变量和块参数,不同的类型参数可使用不同的区域。显示区域的编号由正在编辑的对象类型决定。FB 有 5 个区域类型:
区域 声明 图标IN 输入参数
IN_OUT 输入输出参数
OUT 输出参数
STAT 静态数据(仅针对功能块(FB))
TEMP 临时数据(L 存储区)
2、参数支持的数据类型
输入变量(IN)数据类型:BOOL、BYTE、INT、WORD、DINT、DWORD、REAL、STRINGCHAR;输出变量(OUT)数据类型:BOOL、BYTE、INT、WORD、DINT、DWORD、REAL;输入输出变量(IN_OUT)数据类型:BOOL、BYTE、INT、WORD、DINT、DWORD、REAL;静态变量(STAT)数据类型:BOOL、BYTE、INT、WORD、DINT、DWORD、REAL、FB<nr>、STRINGCHAR;
临时变量(TEMP)数据类型:BOOL、BYTE、INT、WORD、DINT、DWORD、REAL;提示
1)STRING 类型保持与 CTSC-200 PLC 的一致性,STRING 类型占用四个字节,存储的实际内容是一个地址,该地址指向字符串的首地址;
2)STRINGCHAR 类型默认长度为 256 个字节,第一个字节为字符串的长度,从第二个字节起,存储字符串中的每个字符;
3)数据类型 FB 的变量:如果将用户程序结构化,以便 FB 能包含现存功能块的调用,那么可以在调用 FB 的变量声明表中包含作为数据类型 FB 的静态变量调用的FB。允许在一个背景数据块(多重实例)中嵌套变量和集中实例数据,最大允许嵌套多重实例的层数为7 层,嵌套只支持单向性(比如 FB5 组态 FB4,FB4 组态 FB3,FB3 组态 FB2,FB2 组态FB1,此时FB3允许组态 FB1 和 FB2,而不能够组态 FB3/FB4/FB5)。
3、支持参数、临时变量、静态变量的数目
FC 支持 IN/OUT/IN_OUT 的总数最多 62 个,FB 支持 IN/OUT/IN_OUT 的总数最多60个,临时变量占用的空间和参数占用空间的总大小不超过 128 个字节(临时)。FB 支持静态变量的数目,受背景数据块最大空间的限制,即 FB 组态的总大小,不能超过背景数据块的最大空间。
临时变量与静态变量
PLC编程系统44
临时变量(TEMP):相关块执行完毕后被清除,临时存储在 L stack 中。静态变量(STAT):相关块执行完毕后仍然保持,存储在 DB 中;只能在FB 中使用。 列属性
从左到右依次表示内容为:名称、变量类型、数据类型、地址、初始化值、注释;列 说明
名称
字母、汉字、数字字符和下划线组成;字母开头;名称不能以下划线结尾;禁止出现两个连续的下划线;最大长度限制为 23 个字符;禁止使用关键字,变量名不能重复。
数据类型
BOOL、BYTE、INT、WORD、DINT、DWORD、REAL、STRINGCHAR和FB。
可以在数据类型列的下拉列表中选择,String 变量占用256 个字节(首字节表示长度,其他 255 字节存储字符)。
地址 是相对于分配的 DB 区首地址的偏移量,根据数据类型自动分配。初始化值
对内存初始化,语法自动检查,错误的值以红色字体显示,变量声明后使用默认的初始值。BOOL 型默认初始值是 OFF;整型默认初始值是0;浮点型默认初始值是 0.0;StringChar 型默认初始值是””(空)。注释 最多支持 79 个字符
将初始值分配给形式参数
可以在 FB 的声明部分将初始值分配给形式参数。这些值写入到与 FB 有关的实例DB中。如果在调用声明中没有将实际参数分配给形式参数,则将使用保存在实例DB 中的值。这些值也可以是在 FB 变量声明表中输入的初始值。除了临时变量之外,IN/OUT/IN_OUT/STAT都允许分配初始值。
删除/插入块的参数
当一个块已在程序中被调用之后,再增加或删除块的参数,必须更新其他块中的该块的调用。否则,由于在调用时该块新增的参数没有被分配实际参数,则 CPU 会STOP 或者块的功能不能实现。比如,新插入一个参数,它必须在所有块调用中提供实际参数。当块的声明表由于插入或删除形式参数被修改之后保存时,将弹出警告信息,提示可能出现的问题。程序编辑区
生成背景数据块
生成一个新的背景数据块有以下两种方法:
1、在调用 FB 时,为 FB 指定一个背景 DB 后,如果该数据块不存在则弹出以下提示信息,单击【是】按钮可自动生成一个新的背景数据块。
MagicWorks PLC 编程软件用户手册
45
2、创建一个新的 DB 时,选择其类型为【背景数据块】,并指定为某个FB 的数据块。输出窗口
支持单独块的编译功能,在用户打开的当前程序编辑区中可以看到编译的最新消息,在程序编辑区最下方的输出窗口显示编译的错误等信息,该区可以根据用户的配置显示或隐藏。程序元素表
程序元素标签中新增两个元素:功能块(FB blocks)、多重实例(Multiple instance)预组态的的功能块(FB blocks)
展开已有的功能块生成的指令,供程序的 CALL 指令进行调用;
已声明的多重实例(Multiple instance)
通过声明一个具有功能块数据类型的静态变量,创建一个多重实例。只在程序元素目录中包括已经声明的多重实例。多重实例的符号改变取决于是否带参数以及带多少个参数。在变量中声明多重实例
下列规则均适用于多重实例的声明:
1)必须将背景数据块分配给在其中对多重实例进行声明的功能块;2)只能将多重实例声明为静态变量(说明类型为 STAT);功能块的使用
功能块是一种带数据块(DB 块)的块,功能块中的参数值会保存到与它关联的背景数据块中,临时变量保存到本地数据堆栈中。
FB 执行完成后,它的参数值会一直保存到实例 DB 中,不会丢失(临时变量会丢失)。例如:下图为 FB1 的参数
PLC编程系统46
下图为 FB1 关联的实例 DB(背景 DB):
可以看到实例 DB 与 FB1 的参数是一一对应的,FB1 执行完后,FB1 参数的值会保存到实例DB 中对应的变量中。
功能块(FB)可以当成一种特殊的功能(FC):与 FC 相比,FB 多了一个DB 类参数。调用功能块
1)打开【程序块】界面,在左侧的指令树中找到 FB 块节点,如图:2)双击或拖拽相应的 FB 至程序编辑器中:
3)然后输入参数,FB 需要一个 DB 类型的参数,在指令的顶部输入,如下图所示:
MagicWorks PLC 编程软件用户手册
47
若输入的 DB 块参数不存在则会提示是否生成:
4)在调用 FB 后,如果修改了被调用 FB 的输入输出参数列表,则所有调用此FB的地方,此FB 的参数都会变成红色,表示 FB 的接口改变了:
此时需要把此调用删除,并重新调用。
在调用 FB 后,如果修改了被调用 FB 的 STAT 参数列表,则所有调用此FB 的地方,此FB的DB 参数会变红,表示 FB 的接口改变了:
此时只需用鼠标点击变红的 DB 参数,再点击其它的地方,则会弹出提示:选择【是】,即可重新生成背景数据块。
调用多重实例
PLC编程系统48
多重实例即 FB 以另一个 FB 作为它的 STAT 类型的参数,以 FB1 作为FB 的STAT 参数,如图:此时在左侧的指令树中多重实例节点就可以看到 STAT_1:
双击或拖动 STAT_1 到程序编辑器即可:
<备注> 多重实例没有 DB 类型的参数(背景数据块),它使用宿主的背景数据块(DB),宿主指调用这个多重实例的块。
5.3.3 FC 功能
功能(FC)属于个人编程的块。功能是一种不带存储器的逻辑块。属于FC 的临时变量保存在本地数据堆栈中。执行 FC 时,该数据将丢失。为永久保存该数据,功能也可使用共享数据块。由于 FC 本身没有存储器,因此必须始终给它指定实际参数。无法给 FC 的本地数据分配初始值。应用
FC 包含由另一个逻辑块调用该 FC 时,始终执行的程序段。可使用下列功能:▪ 将功能值返回调用块(例如,算术功能)
▪ 执行技术功能(例如,具有位逻辑操作的单个控制功能)
将实际参数分配给形式参数
形式参数是实际参数的哑元。调用该功能时,实际参数将替换形式参数。必须始终将实际参数分配给 FC 的形式参数。FC 所使用的输入、输出以及输入/输出参数作为指针保存到调用FC的逻辑块的实际参数中。
FC 和 FB 输出参数之间的重要区别
在功能块(FB)中,访问参数时,使用背景数据块中的实际参数副本。如果调用FB时,没有传送输入参数或没有写访问输出参数,那么将使用原先保存在背景数据块(背景数据块=FB存储器)中的值。
但功能(FC)没有存储器,因此,与 FB 相反,必须将形式参数分配给这些FC。通过地址(指针跨过区域边界指向目标)访问 FC 参数。当数据区(数据块)地址或调用块的局部变量用作实际参数时,实际参数的副本将临时保存到用于传送参数的调用块的本地数据区中。<警告> 此时,如果没有数据写入到 FC 中的 OUTPUT 参数,那么该块可能输出随机值。如果没有将保留给副本的调用块的本地数据区分配给 OUTPUT 参数,因此没有数据写入到该区域。由此,该区保持不变,例如,由于缺省情况下本地数据没有自动设置为0,所以将输出在该位置保存的随机值。
MagicWorks PLC 编程软件用户手册
49
因此,请遵守下列几点:
● 如有可能,请初始化 OUTPUT 参数。
● 始终确保将数据写入到 OUTPUT 参数中,而与块中的程序路径无关。<注意> 虽然 FB 的 OUTPUT 参数或 FC 和 FB 的 OUTPUT 参数不会输出随机值(即使没有数据写入到该参数中,也保持原输出值或作为输出值的输入值),仍然应该遵守上述各点注意事项,避免意外处理“原”值。
5.3.4 DB 数据块(CTH300 系列 PLC 适用)
数据块是中型 PLC 支持的一种存放数据的块。与逻辑块相反,数据块不包含PLC指令。它们用来存储用户数据,即数据块包含用户程序使用的变量数据。其中共享数据块可用来存储可由所有其它块访问的用户数据。
数据块与 CTSC-200 PLC 的 V 内存不同,需要用户创建并在数据块中声明需要的数据类型后,才能够使用。从这个意义上来讲,V 内存可以理解为一种特殊的数据块,在PLC中已经默认分配好空间的数据块。
数据块的编辑方式不同于 CTSC-200 PLC 中的 V 内存,使用独立的编辑器datablockeditor.exe来打开、编辑、修改、保存数据块中的数据。创建数据块的方式与创建逻辑块OB/FC/FB一致,在工作区域的空白处点击右键→【插入新对象】→【数据块】来弹出数据块的属性,再经过用户配置后,可以创建对应的数据块。
数据块包括共享数据块和背景数据块,它们分别有以下功能:
● 共享数据块的新建、编辑、下载、监控功能;
● 背景数据块的新建、下载、监控功能;数据块的基本信息
可以在数据块(DB)中存储数值以便为机器或设备所访问。与逻辑块OB/FB/FC相比,数据块只包含变量声明部分。这就表示此处与代码段和编程段无关。
数据块支持声明视图和数据视图,使用菜单命令【视图】→【声明视图】或【数据视图】,可在这两种视图之间切换。
声明视图
1)新建、编辑、修改共享数据块的数据结构;
2)查看相关功能块(FB)的数据块的数据结构。
在声明视图中,不能修改与功能块相关联的数据块的结构。若要修改它们,必须首先修改相关的 FB,然后创建一个新的数据块。只有共享的数据块,才能改变声明视图。声明视图中列属性的详细解释:
列 解释
地址 当输入完声明时,显示自动分配给变量的地址。
声明
仅为实例数据块显示该列。它显示功能块变量声明中的变量是如何声明的:输入参数(IN)
输出参数(OUT)
输入/输出参数(IN_OUT)
静态数据(STAT)
PLC编程系统50
名称 在此输入必须为各个变量分配的符号名称。
类型
输入希望分配给变量的数据类型(BOOL、INT、WORD、等等)。变量可以有基本数据类型、复杂数据类型或用户自定义数据类型。初始值
如果不希望使用所输入数据类型的默认值,那么可以在此输入初始值。所有的值都必须与数据类型兼容。当首次保存块时,如果没有明确定义变量的实际值,那么,初始值将作为当前值使用。
<注意> 初始值不能下载给 CPU。
注释 在该域中输入一条注释,有助于对变量编写文档。数据视图
数据视图显示数据块中所有变量的当前值。只能在数据视图中改变这些值。对于所有共享数据块,该视图中的表格表示均相同。对于背景数据块,将显示一个附加的【声明】列。数据视图列属性的详述:
列 解释
地址 自动为变量分配的地址。
声明
仅为实例数据块显示该列。它显示功能块变量声明中的变量是如何声明的:输入参数(IN)
输出参数(OUT)
输入/输出参数(IN_OUT)
静态数据(STAT)
名称 在变量声明中为变量分配的符号名称。在数据视图中不能编辑该域。类型
显示为变量定义的数据类型。 对于共享数据块,这里将只列出基本数据类型,因为对于具有复杂或用户自定义数据类型的变量,其元素将在数据视图中逐个列出。对于实例数据块,还会显示参数类型,对于具有复杂或用户自定义数据类型的输入/输出参数(IN_OUT),指针将指向\"实际值\"列中的数据类型。变量初始值
如果不希望使用指定数据类型的默认值时,可以为变量输入初始值。当首次保存数据块时,如果没有明确定义变量的实际值,将使用初始值作为当前值。<注意> 与实际值不同,初始值不能下载给 CPU。
实际值
打开数据块时的变量值,或上一次修改、保存过的变量值。如果在监控状态下则为 CPU 中变量的值。
注释 所输入的用来为变量编写文档的注释。在数据视图中不能编辑该域。共享数据块和背景数据块之间的差别
共享数据块:共享数据块是全局共享的,可以随意修改数据块中的变量。背景数据块:背景数据块和特定的 FB 关联,不能随意修改里面的变量,只能通过FB生成,新建一个数据块时可以指定它与一个 FB 块关联。背景数据块中的变量是与它关联的FB的输入输出及静态参数。
共享数据块支持的数据类型:BOOL、BYTE、INT、WORD、DINT、DWORD、REAL、STRINGCHAR;
背景数据块支持的数据类型:BOOL、BYTE、INT、WORD、DINT、DWORD、REAL、STRINGCHAR、FB<nr>;
数据块编号的取值范围和大小
MagicWorks PLC 编程软件用户手册
51
数据块编号的取值范围:1~254;
每个数据块的最大空间为:64K(65536 个字节);
数据块中允许创建的最大行数:组态数据块的大小,只要未超过单个数据块的最大空间64K,则允许用户一直创建。数据块的监控
声明视图下的监控
声明视图不支持监控模式,在声明视图下启动监控模式时,会弹出提示【当前模式不支持监控功能,是否跳转到数据视图进行监控】,选择【是】,则跳转到数据视图进行监控;在用户取消监控后,会跳转回声明视图模式。
数据视图下的监控
数据视图启动监控模式,会在【实际值】列显示 CPU 中对应的数据值,而且只有实际值列可以修改;支持 STRINGCHAR 数据类型的监控。
DB 块的使用
新建数据块
● 在 CTH300 系列 CPU 站点下选择程序块,右键选择【插入新对象】→【DB】插入新的DB块,如下图所示:
选择【DB】后会弹出如下对话框:
PLC编程系统52
在此可以设置新数据块的名称、符号名等属性,配置完后点击【确定】即可完成数据块的创建。● 在程序块界面双击建好的 DB 数据块,进入 DB 参数设置界面,在该界面菜单项选择【文件】→【新建】,会弹出如下对话框:
输入 DB 块名称后点击【确定】,会弹出如下对话框:
此处可以选择新建共享数据块还是背景数据块。如果选择了背景数据块下面的列表会列出可以关联的 FB,如下图:
MagicWorks PLC 编程软件用户手册
53
选择关联的 FB 后,点击【确定】完成数据块的创建。
插入行
只有共享数据块才可以插入行,具体操作如下:
选择菜单项【视图】→【声明视图】即切换到声明视图;
选中一个单元格:单击右键选择【在前面插入】/【在后面插入】即可在当前单元格前面或后面插入一行数据。
删除行
只有共享数据块才可以删除行,具体操作如下:
选择菜单项【视图】→【声明视图】即可切换到声明视图;
选中单行或多行数据,单击右键选择【删除】。
修改变量名称:双击【名称】列,即可对变量名称进行编辑。
修改变量类型:右键点击【类型】列→【数据类型】,如下图:
PLC编程系统54
修改列宽
在 DB 参数页面选择菜单项【视图】→【列宽】弹出以下窗口,可进行表格各项内容列宽设置:编译:点击工具栏的编译按钮 或选择菜单项【PLC】→【编译】则只编译改动过的程序块;若选择【PLC】→【重新编译程序块】则将编译所有程序块,包括未改动程序块。下载:点击工具栏的下载按钮 或选择菜单项【PLC】→【下载】
写入
只有在监控状态下才可以写入;
只有在修改了实际值时才可以写入,否则写入菜单为灰色;
修改了实际值后,被修改的行监控会暂停,只有写入后才会继续监控;写入过程:
1)进入监控模式
2)修改实际值
3)点击工具栏写入按钮 或选择菜单项【PLC】→【写入】
监控
1)选择菜单项【视图】→【数据视图】即切换到数据视图
2)工具栏点击监控按钮 或在菜单项选择【调试】→【监控】即可切换到监控画面使用 DB 块变量
1、通过直接地址使用
DB [number].DB [X,B,W,D][byteoffset].[bitoffset]
[number]为数据块编号,[X,B,W,D],表示数据类型,[byteoffset]表示字节偏移,[bitoffset]表示
MagicWorks PLC 编程软件用户手册
55
位偏移。例如:
位变量:DB1.DBX0.0
字节变量:DB1.DBB0
字变量:DB1.DBW0
双字变量:DB1.DBD0
2、通过符号使用
[DBsymbol].[varsymbol]
[DBsymbol]表示数据块的符号(新建数据块时可以输入),[varsymbol]表示数据块中变量名(数据块中的名称列)。例如:
ABC.var_1
5.4 C 程序块
C 函数编程语言是 MagicWorks PLC 软件功能的升级加强。在原有梯形图和STL 两种编程语言基础上,允许 C 函数编程与梯形图等编程语言一起工作。利用 C 语言编写功能块,增强程序的可读性和维护性,同时,C 语言丰富的运算函数可实现各种调用功能,节省了内部空间,也提高了编程效率。目前支持 C 程序块编程的 PLC 型号如下:
CPU 系列 型号
CTMC 系列 V2.84 及以上固
件版本
M228IL、M228ML、M228SL、M226SM
CTH200 系列
V5 平台:H224X、H226XL、H226XM
I6 平台:H226IM、H226IL、H226IH
CTSC200 系列 V5 平台:224+、224I、224XP、226I、226M、226L、226HCTH300-H 系列 H31-01、H32-01、H35-01、H36-01、H52-10、H56-10本章介绍 MagicWorks PLC 的 C 语言编程功能的使用,具体内容如下: 在 Magicworks PLC 中的 C 语言编程步骤
C 语言基础
运算符与表达式
for 循环语句
选择语句
libplc300.a 库的介绍
5.4.1 在 Magicworks PLC 中的 C 语言编程步骤
1、在 MagicWorks PLC 中新建项目,选择【程序块】后右键点击空白处,选择【插入新对象】【C 程序块】。
PLC编程系统56
2、编辑 C 程序属性,此处定义的符号名将自动作为 C 函数名,建议不要用中文定义,复制代码时 CF 块的符号名与 C 语言函数名一定要相同,否则将不执行。如果工程师希望进行代码保护,也可以参考以下步骤增加密码保护。
3、函数创建成功后,可在程序块中看到 CF0。
MagicWorks PLC 编程软件用户手册
57
4、双击 CF0,进入 C 函数程序编程窗口。MagicWorks PLC 新建 CF0 后会默认加入以下三个头文件。
5、在局部变量窗口中定义需要外部输入或输出的参数值,全部定义完成后点击【】初始化C程序块,重新生成函数模板。C 函数的名称和函数参数不要随便改动。
PLC编程系统58
<备注> 局部变量窗口最多只能定义 16 个变量。
6、在生成的模板中,编写程序,编程完成后点击执行编绎操作,输出窗口中若无提示错误,即可被 OB1 或其他 FC 调用。从参数符号表定义的参数,输入参数会转变C 语言相应类型的输入参数,参数可以直接使用;而输入输出和输出参数,会变成相应类型的指针,通过指针在C函数里将结果写回 STL 系统,即 C 函数无返回值,返回值只能通过指针传回。7、编写完成的 C 函数子程序,需在 OB1 主程序或者其它执行的 FC 中调用。当执行程序块下载时,C 子程序也将一同下载到 PLC 中。(注:C 函数内部不可在线监控,但是在梯形图调用处是可以监控输入输出的)。以下程序执行的功能为:如果 M0.0=0,则vw4=vw0+vw2;如果
MagicWorks PLC 编程软件用户手册
59
M0.0=1,则 vw4=vw0-vw2。
PLC编程系统60
5.4.2 C 语言基础
头文件
编译器提供了许多在头文件中声明的标准函数。头文件也称为包含文件,头文件作为一种包含功能函数、数据接口声明的载体文件,主要用于保存程序的声明。
头文件 说明
<stdio.h> 输入输出函数
<stdarg.h> 支持变元个数可变函数的宏
<math.h> 数学浮点函数
<stdlib.h> 内存分配函数
<string.h> 字符串处理函数
<stdbool.h> bool 类型和布尔值 true 和 false
<complex.h> 支持复数
<ctype.h> 字符分类函数
<wctype.h> 宽字符转换函数
头文件包含了各种函数的声明以及各种变量的声明,MagicWorks PLC 新建C 程序块后会默认加入以下头文件。
#include \"math.h\" #include \"stdio.h\" #include \"plc300.h\"(CTH300 系列 PLC)
#include \"plc200.h\"(小型 PLC)
其中,头文件<stdio.h>含有大量高级输入/输出(I/0)函数的声明,是 C 语言中的标准输入输出头文件,stdio 即 stand input output 的缩写,程序中含有输入输出操作,就必须使用该头文件。头文件<math.h>中声明了常用的一些数学运算,比如乘方,开方运算、求三角函数、对数之类的函数,可以直接调用。
“plc300.h”、“plc200.h”是合信自己开发的库 libplc300.a,libplc200.a 对应的头文件,用户通过这两个库能够调用底层函数和 STL PLC 系列进行交互,用户可以使用的函数可在头文件中查看,头文件在编程软件安装目录\\ccompile\\include\\plc300.h 中。变量
1、定义变量
变量定义的一般形式:数据类型 变量名
例如:FP32 real1; //定义 32 位浮点数
S16 int1; //定义 16 位有符号整型
const FP32 PI=3.1415926; //定义 32 位浮点数常量 PI
局部变量窗口定义的参数值,执行【初始化 C 程序块】,程序编程窗口会自动将参数定义到子程序中。
MagicWorks PLC 编程软件用户手册
61
注意:
变量名必须以字母或下划线开头,名字中间只能由字母、数字和下划线_组成;最后一个字符可以是类型说明符。
变量必须先定义,后使用。
一个变量名只能定义一次,变量建议定义在程序头部,变量定义不允许使用中文变量,且严格区分大小写。
一些较简单的字符变量名容易跟一些原有计数器混淆,例如 c 表示计数器,c1 就不允许使用。2、static 局部变量与普通变量
局部变量与普通变量的区别
1) 内存分配和释放
普通局部变量只有执行到变量定义的语句时才分配空间。
static 局部变量在编译阶段(函数还没有执行),变量的空间已经分配。 普通局部变量离开作用域{},自动释放其空间,也就无法使用此变量。 static 局部变量只有在整个程序结束的时候才将其自动释放。
2) 初始化
普通局部变量不初始化,为随机值。
static 局部变量不初始化,为 0。
static 局部变量初始化语句只有第一次执行时有效,但是可以赋值多次。 static 局部变量只能用它常量初始化。
变量在全局数据区分配内存空间;编译器自动对其初始化其作用域为局部作用域,当定义它的函数结束时,其作用域随之结束。
C 语言编程举例如下:只要 var1 不等于 0,则 var2 加一。
void CF_3( S16 var1, S16 *var2 )
{
static S16 temp;
if(var1!=0)
{
temp=temp+1;
}
setS16(var2,temp);
} //temp 变量用 static 修饰符
PLC编程系统62
注释的使用
编写 C 语言时使用注释有助于对代码的理解,注释不进行编绎,不会影响程序的执行。在C语言中有两种注释方式:
以/*开始、以*/结束的块注释(block comment)
以//开始、以换行符结束的单行注释(line comment)
Magicworks PLC 中既可手动注释,也可以采用注释键进行注释。点击菜单栏中的注释键即可注释,点击菜单栏中的取消注释键 即可取消注释。各类数值型数据间的混合运算
在进行运算时,不同数据的类型需要转换成同一类型数据,然后进行运算。运算过程:先自动转换成同类数据,再进行运算。
转换规则:低字节类型转换成高字节类型。
C 语言编程例程:c = S16 a + FP32 b,a 将自动转换为 FP32 的数据类型,再与b 相加,结果得到一个 FP32 型的 c。
C 语言编程如下:
#include \"math.h\" #include \"stdio.h\" #include \"plc300.h\" void CF_2( S16 data_a, FP32 data_b, FP32 *data_c )
{
FP32 temp;
temp=data_a+data_b;
setFP32(data_c,temp);
}
编译后得到的 CF 块,通过 OB1 或者其他 FC 调用:强制类型转换
将指定表达式的值转换为指定类型,需要编程者指定需要转换的类型。形式:(类型名)(表达式)
例如:(S16)(a+b)
说明:1)类型名和表达式需加括号
2)在强制类型转换时,得到一个所需类型的中间变量,原来变量类型未发生变化。
MagicWorks PLC 编程软件用户手册
63
C 语言编程例程:将一个 32 位浮点数四舍五入取整然后转换成 16 位整数。void CF_2(FP32 data_b, S16 *data_c )
{
S16 temp;
If (data_b>0)
{
temp=(S16)(data_b+0.5);
}
else
{
temp=(S16)(data_b-0.5);
}
setS16(data_c,temp);
}
编译后得到的 CF 块,通过 OB1 或者其他 FC 调用:数组
数组是一组有序数据的集合,若将有限个类型相同的变量的集合命名,这个名称为数组名;数组中每个元素的数据类型都相同,用户通过数组名和下标来确定数组中的元素。一维数组的定义方式:类型说明符 数组名[整形常量表达式]
例如:FP32 real0[10];
说明:定义了一个数组,数组名为 real0,有 10 个元素,每个元素的类型均为FP32 型;这10个元素分别是 real[0]、real[1]、real[2]、……real[8]、real[9]。
初始化数组:数组可在声明的初始化,初始化数组时,各个索引变量的值要封闭在{}内,并用逗号分隔,例如:S16 aa[3]={2,6,1};等价于:S16 aa[3];aa[0]=2;aa[1]=6;aa[2]=1;
注意:
下标从 0 开始。如:数组第 1 个元素为 real1[0],第 8 个元素为 real1[7]。 C 语言一般是不允许对数组的大小做动态定义的,如 FP32 real1[n],这是不允许的。 语言不检查数组下标越界,因此使用时不要越界使用,本例中数组元素个数是10 个,下标范围为:0-9,不能超出 9。
数组中的各元素的存储是有先后顺序的,它们在内存中按照这个先后顺序连续存放在一起。C 语言编程示例:将 VD100 开始连续 10 个值,复制到 VD200 后。void CF_0( void* real1, void* real2 )
{
S16 i,j;
FP32 temp[10] ={0,0,0,0,0,0,0,0,0,0}; //定义数组
for (i=0;i<10;i++)
{
temp[i]=getFP32(real1+4*i); //数组地址
}
for (j=0;j<10;j++)
{
set FP32((real2+4*j),temp[j]);
PLC编程系统64
}
}
调用生成的 CF0
状态表结果如下所示:
赋值运算符与赋值表达式
1、赋值运算符=赋值表达式:将一个数值赋给一个变量或将一个变量的值赋给另一个变量。赋值形式:变量名=常量或表达式;
赋值作用:将右边常量或表达式的值赋给左边的变量。如: a=3、a=b*c
注意:
所有的语句,包括赋值语句,必须要以分号【;】结尾。
赋值后,原来左边的值被右边表达式的值替换
如果右边表达式的值类型与左边变量的类型不一致,以左边变量的类型为准,将右边表达式值的类型自动转换为左边变量的类型。
MagicWorks PLC 编程软件用户手册
65
2、多重赋值运算符:多重赋值是将表达式的值同时赋给几个变量,在这种情况下,要把被赋值的变量名按次序写在赋值号的左边。
赋值形式:变量 1=变量 2=…=变量 n=表达式
等价于:变量 1=(变量 2=(…=(变量 n=表达式)))
例如:a=b=c=7;
3、复合赋值运算符:在赋值符=之前加上其它运算符。常见的有:+=、-=、*=、/=、%=复合赋值运算的功能:与左边的变量进行复合运算后再赋给左边的变量。例如:
a+=3; 等价于 a=a+3
x*=y+8; 等价于 x=x*(y+8)
x%=3; 等价于 x=x%3
int a=1,b=2,c=2; c*=a-b; 等价于 c=c*(a-b)=2*(-1)=-2
算术运算符
C 语言中的算术运算符有:
算术运算符 意义
+ 加或取正值运算符
- 减或取负值运算符
* 乘运算符
/ 除运算符
% 取余运算符
其中,加减乘除均为算术运算符,要求有两个运算对象。自增自减运算符
运算符说明:++表示自增,变量值加 1,
--表示自减,变量值减 1。
用法 1:单独作为一个表达式被使用。例如:i++或者++i 等价于 i=i+1
用法 2:出现在其他表达式中参与运算,++i/--i 表示 i 自增/自减 1 后再参与其它运算;而i++/i--则是 i 参与运算后,i 的值再自增/自减 1。
例如:S16 j,i=3;
j=++i; // i,j 的值为 4
j=i++; // j 的值为 4,然后 i 的值变为 5
j=-(i++); // j 的值为-5,然后 i 的值变为 6
关系运算符与表达式
关系运算:比较两个操作数是否满足给定的关系,用于简单的条件判断。在C 语言中有以下关系运算符:
(1) < 小于
(2) <= 小于或等于
(3) > 大于
(4) >= 大于或等于
PLC编程系统66
(5) == 等于
(6) != 不等于
关系运算符的结果只能是 0 或者 1,值为真时结果为 1,值为假时结果为0。例如:3.24<=2.98; //值为假,运算结果为 0
0.5!=3+1; //值为真,运算结果为 1
关系表达式:用关系运算符将两个表达式(算术表达式、关系表达式、逻辑表达式、赋值表达式、字符表达式)连接起来的式子,称为关系表达式
关系表达式的一般形式为:表达式 关系运算符 表达式
关系运算符的优先级低于算术运算符,高于赋值运算符。
例如:a=1+2>3-1; //等价于 a=((1+2)>(3-1)),结果为 a=1
逻辑运算符与表达式
逻辑运算也称布尔运算,用于复杂的条件判断。
运算符 含义 优先级 ST 描述! 逻辑非 1 NOT
&& 逻辑与 2 AND
ll 逻辑或 3 OR
逻辑表达式的一般形式:表达式 逻辑运算符 表达式
逻辑运算真值表
A 取值 B 取值 !A A&&B AllB非 0 非 0 0 1 1
非 0 0 0 0 1
0 非 0 1 0 1
0 0 0 0 0
C 语言编程例程:当(a>b)&&(b>c)结果为真时 d=1,当(a>b)&&(b>c)结果为假时d=0。void CF_1( BOOL *data_d )
{
S16 data_a=3,data_b=2,data_c=1;
if ((data_a>data_b)&&(data_b>data_c))
{ *data_d=1;
}
else
{ *data_d=0;
}
}
编译后得到的 CF 块,通过 OB1 或者其他 FC 调用:
MagicWorks PLC 编程软件用户手册
67
条件运算符与条件表达式
条件运算符与条件表达式 有两个符号:问号和分号,它与三个操作数组成三元运算。一般形式:<表达式 1>?<表达式 2>:<表达式 3>
优先级:逻辑>条件>赋值
例如:S16 max,a=5;b=3;
max=a>b?a:b
结果:max=5
C 语言编程例程:比较 2 个值的大小,并将最大值输出。
void CF_0( FP32 real1, FP32 real2, FP32 *max )
{
FP32 max_t;
max_t=real1>real2?real1:real2;
setFP32(max,max_t);
}
编译后得到的 CF 块,通过 OB1 或者其他 FC 调用:
for 循环语句
在应用程序中,需要多次执行某些步骤,这个过程叫循环;for 循环是编程语言中一种循环语句,循环程序的设计需要建立程序使它能够循环返回并循环执行自身程序。for 循环语句的一般形式:
for(单次表达式;条件表达式;末尾循环体)
{
中间循环体;
}
例如:for (i=1;i<=100;i++)
{
sum=i+sum;
}
for 循环中的语句反复被执行,每次循环后,变量 i 会自动加 1。i=1 和i<=100 是循环控制变量的起始值和终止值。当控制变量达到终止值时,程序就执行 for 语句后的下一条指令。例如:求 1-20 的平方和!
void CF_1( S16 *int3 )
{
S16 int3_t=0;
S16 i;
for (i=1;i<=20;i++)
PLC编程系统68
{
int3_t=int3_t+i*i;
}
setS16(int3,int3_t);
}
编译后得到的 CF 块,通过 OB1 或者其他 FC 调用:
if 选择结构语句
if 选择结构:判断 if 条件,根据判断结果执行后续操作的选择结构。1)单分支 if 选择结构的一般格式:
if(表达式) //表达式:指判断条件,真为 1,假为 0
{
执行语句; //仅当表达式为真时,才执行此处执行语句
}
例如:输入一个数,判断能否被 4 或者 7 整除,满足条件输出为 1。void CF_0( S16 int1, S16 *out1 )
{
S16 out_t=0;
if (int1%4==0||int1%7==0)
{
out_t=1;
}
setS16(out1,out_t);
}
编译后得到的 CF 块,通过 OB1 或者其他 FC 调用:
2)双分支 if 选择结构的一般格式:
if(表达式) //表达式:指判断条件,真为 1,假为 0
{
执行语句; //仅当表达式为真时,才执行此处执行语句
}
else
{
执行语句; //条件为 0,执行 else 后的语句
}
例如:输入一个数,偶数输出 a,奇数输出 b。
void CF_0(S16 int1, U8 *out1 )
{
char out;
if (int1%2==0)
{
out='a';
MagicWorks PLC 编程软件用户手册
69
}
else
{
out='b';
}
setU8(out1,out);
}
编译后得到的 CF 块,通过 OB1 或者其他 FC 调用:
3)多重 if 选择结构的一般格式:
if(表达式)
{
执行语句;
}
else if(表达式 1)
{
执行语句;
}
else if(表达式 2)
{
执行语句;
}……
else
{
执行语句;
} //最后一个 else{}可以省略,有则必须放在 else if 后面
例如:输入成绩,大于等于 90 为 A,80-89 为 B,70-79 为 C,60 到69 为D,低于60为E。多重 if 执行的流程图如下:
C 语言编程如下:
void CF_1( S16 score, U8 *level )
{
PLC编程系统70
char level_t;
if (score>=90)
{
level_t='A';
}
else if (score>=80)
{
level_t='B';
}
else if(score>=70)
{
level_t='C';
}
else if(score>=60)
{
level_t='D';
}
else
{
level_t='E';
}
setU8(level,level_t);
}
switch 多分支选择语句
switch 语句是多分支条件判断语句,它根据表达式的值使程序从多个分支中选择一个用于执行的分支。
switch 的一般格式:
switch(表达式)
{
case 常量表达式 1 : 语句 1;
break;
case 常量表达式 2 : 语句 2;
break; ……
case 常量表达式 n : 语句 n;
break;
default : 语句 n+1;
}
注意:
case 条件执行语句后需加 break 跳出 switch 结构,否则无法分支; 常量表达式的值必须互不相等,否则有二异性;
case 的顺序无关紧要, default 可有可无。
switch 语句不等同于 if 语句,switch 只能进行值的相等性检查,不是逻辑判断;if 语句不但可以进行值的相等性判断,还可以计算关系表达式或逻辑表达式,进行逻辑判断的真假。例如:
void CF_0( S16 Level, BOOL *heat1, BOOL *heat2, BOOL *heat3, BOOL *fan )
{ *heat1=*heat2=*heat3=*fan=0;
MagicWorks PLC 编程软件用户手册
71
switch (Level)
{
case 1:*fan=1;
break;
case 2:*fan=0;
break;
case 3:*heat1=1;
break;
case 4:*heat1=*heat2=1;
break;
case 5:*heat1=*heat2=*heat3=1;
break;
default:*heat1=*heat2=*heat3=1;
}
}
5.4.3 libplc300.a/ libplc200.a 库介绍
libplc300.a/libplc200.a库为Magicworks PLC自带的库,该库中含有从STL取值和将值写回STL的函数以及 STL 系统与 C 语言系统的数据转换操作函数,用户可直接调用这些函数。用户可以使用的函数可在头文件 plc300.h 或 libplc200.a 中查看,头文件 plc300.h 或libplc200.a 在编程软件安装目录\\ccompile\\include\\plc300.h 里。
下面将对 C 程序块的数据类型以及各种操作函数进行介绍。
CF 块参数符号表中可选择的数据类型
类型 说明typedef unsigned char BOOL; 8bit 无符号
typedef unsigned char U8; 8bit 无符号
typedef signed char S8; 8bit 有符号
typedef unsigned short U16; 16bit 无符号
typedef signed short S16; 16bit 有符号
typedef unsigned int U32; 32bit 无符号
typedef signed int S32; 32bit 有符号
typedef float FP32; 单精度浮点
typedef double FP64; 双精度浮点
typedef long long S64; 64bit 无符号
typedef unsigned long long U64; 64bit 有符号
typedef unsigned char BYTE; 8bit 无符号
typedef unsigned short WORD; 16bit 无符号
PLC编程系统72
typedef signed short INT; 16bit 有符号
typedef unsigned int DWORD; 32bit 无符号
typedef signed int DINT; 32bit 无符号
typedef float REAL; 单精度浮点
大小端转换
由于 STL 系统的数据使用的是大端模式,而 C 语言使用的是小端模式,因此直接操作指针赋值会有字节序混乱的问题,因此我们提供了一组通过指针从 STL 取值和将值写回STL 的函数,函数的具体形式在 MagicWorks PLC 安装目录\\ccompile\\include\\plc300.h 里。大端模式:数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。参数通过指针在 C 语言系统和 STL 系统进行传递时,由于 C 语言系统使用的是小端模式,而STL 系统使用是的大端模式,所以需要调用大小端转换接口。
STL 系统与 C 语言系统的数据转换操作函数
1、通过指针将值写回 STL 环境:由于输入输出和输出参数会变成相应类型的指针类型,且大小端转换的问题,所有的输入输出或输出参数都要通过以下指令将结果从C 语言写回到STL环境。
函数 描述 输入返回void setBOOL(BOOL
*p, BOOL d)
将一个 BOOL 数据,从 C
语言写回 STL 系统
p:从 STL 系统传过来的指针d:C 语言所用的BOOL 数据无void setU8(U8 *p, U8
d)
将一个 U8 数据,从 C 语
言写回 STL 系统
p:从 STL 系统传过来的指针d:C 语言所用的U8 数据无void setS8(S8 *p, S8
d)
将一个 S8 数据,从 C 语
言写回 STL 系统
p:从 STL 系统传过来的指针d:C 语言所用的S8 数据无void setU16(U16 *p, U16 d)
将一个 U16 数据,从 C
语言写回 STL 系统
p:从 STL 系统传过来的指针d:C 语言所用的U16 数据无void setS16(S16 *p, S16 d)
将一个 S16 数据,从 C
语言写回 STL 系统
p:从 STL 系统传过来的指针d:C 语言所用的S16 数据无void setU32(U32 *p, U32 d)
将一个 U32 数据,从 C
语言写回 STL 系统
p:从 STL 系统传过来的指针d:C 语言所用的U32 数据无void setS32(S32 *p, S32 d)
将一个 S32 数据,从 C
语言写回 STL 系统
p:从 STL 系统传过来的指针d:C 语言所用的S32 数据无void setFP32(FP32 *p, FP32 d)
将一个 FP32 数据,从 C
语言写回 STL 系统
p:从 STL 系统传过来的指针d:C 语言所用的FP32 数据无
MagicWorks PLC 编程软件用户手册
73
例子如下:输入 int1 与 int2 相加,输出 int4 进行了大小端转换,输出结果正确;输出int3没有进行大小端转换,输出结果不正确。
2、通过指针从 STL 取值:如果在 C 函数输入参数中直接调用 PLC 的V 区、M区等寄存器,可以将 PLC 寄存器的指针输入给 C 函数,通过取指针值的方式获取 PLC 内存区的值到C语言,但必须通过以下函数进行转换。
函数 描述 输入返回U8 getU8(U8 *p) 从 p 地址取得一个 C 语言
系统可用的 U8 数据
p:从 STL 系统传过来的指针C 语言系统可用的U8 数据S8 getS8(S8 *p) 从 p 地址取得一个 C 语言
系统可用的 S8 数据
p:从 STL 系统传过来的指针C 语言系统可用的S8 数据U16 getU16(U16 *p) 从 p 地址取得一个 C 语言
系统可用的 U16 数据
p:从 STL 系统传过来的指针C 语言系统可用的U16 数据S16 getS16(S16 *p) 从 p 地址取得一个 C 语言
系统可用的 S16 数据
p:从 STL 系统传过来的指针C 语言系统可用的S16 数据U32 getU32(U32* p) 从 p 地址取得一个 C 语言
系统可用的 U32 数据
p:从 STL 系统传过来的指针C 语言系统可用的U32 数据S32 getS32(S32* p) 从 p 地址取得一个 C 语言
系统可用的 S32 数据
p:从 STL 系统传过来的指针C 语言系统可用的S32 数据FP32 getFP32(FP32* p)
从 p 地址取得一个 C 语言
系统可用的 FP32 数据
p:从 STL 系统传过来的指针C 语言系统可用的FP32 数据
PLC编程系统74
<备注> 不通过指针从 STL 取值:输入变量不通过指针的方式,而是输入变量直接获取PLC寄存器的值,就不需要使用 get 函数。
C 语言编程如下:
1、将 VW100 开始连续 20 个 VW 值赋给 VW200 地址段。
void CF_2( void* int1, void* int2 )
{
S16 r,i;
for(i=0;i<20;i++)
{
r=getS16(int1+2*i);
setS16((int2+2*i),r);
}
}
调用生成的 CF 块
状态表结果如下所示:
2、将 V 区开始的 LEN 个 INT 值进行大小排序,显示到另一个 V 区。void CF_0( void* varin, S16 len, void* varout )
{
S16 i,j,n,k,l;
S16 temp[len];
for (l=0;l<len;l++) //将 V 区的值存入 temp 数组
{
temp[l]=getS16(varin+2*l);
}
for (i=len;i>1;i--) //冒泡法将大小值排序,每次最大就像气泡一样\"浮\"到数组的上面{
for(j=0;j<i-1;j++) //依次比较相邻的两个元素,使较大的元素向后移if (temp[j]<temp[j+1])
{
n=temp[j];
temp[j]=temp[j+1];
MagicWorks PLC 编程软件用户手册
75
temp[j+1]=n;
}
}
for(k=0;k<len;k++) //将 temp 数组值传出到 V 区
{
setS16((varout+2*k),temp[k]);
}
}
编译后得到的 CF 块,通过 OB1 或者其他 FC 调用:
状态表结果如下所示:
获取内存基地址的操作函数
函数 描述 输入返回*getLBase(void) 描述获取 L 区内存地址 无L 区内存大小*getIBase(void) 获取 I 区内存地址 无I 区内存大小
PLC编程系统76
*getQBase(void) 获取 Q 区内存地址 无Q区内存大小*getAQBase(void) 获取 AQ 区内存地址 无AQ区内存大小*getAIBase(void) 获取 AI 区内存地址 无AI 区内存大小*getSMBase(void) 获取 SM 区内存地址 无SM区内存大小*getTVBase(void) 获取 TV 区内存地址 无TV 区内存大小*getTBBase(void) 获取 TB 区内存地址 无TB 区内存大小*getSBase(void) 获取 S 区内存地址 无S 区内存大小*getCVBase(void) 获取 CV 区内存地址 无CV 区内存大小*getCBBase(void) 获取 CB 区内存地址 无CB 区内存大小*getACBase(void) 获取 AC 区内存地址 无AC区内存大小*getVBase(void) 获取 V 区内存地址 无V 区内存大小*getMBase(void) 获取 M 区内存地址 无M区内存大小IO 相关函数
函数 描述 输入返回U8 ReadExtDI(U16 oft, U8
*Err)
读 扩 展 IO 的 一 个
Byte,不更新内存映射
区。
oft:IB 内存的第oft 个 byte。 Err:存放返回的错误码
0--无错。
其它--访问出错如果没有错误,则是总线扩展IO的实际输入。void WriteExtDQ( U16 oft, U8 Data, U8 *Err )
(200PLC 专用)
写 扩 展 IO 的 一 个
Byte。
新的内容将更新到内
存映射区。
oft:QB 内存的第oft 个 byte
Data:要更新的值
Err:存放返回的错误码。
0--无错
其它--访问出错U16 ReadExtAI(U16 oft, U8 *Err)
读扩展 IO 的一个模拟
输入,更新内存映射
区。
oft:AIW 内存的第 oft 个 通道,0--AIW0。
2--AIW2 奇数无效 Err:存放返回的错误码
如果没有错误,则是模拟的实际输入。
MagicWorks PLC 编程软件用户手册
77
0--无错
其它--访问出错Void WriteExtAQ(U16 oft, U16 Data, U8 *Err)
写扩展 IO 的一个模拟
量输出。
新的内容将更新到内
存映射区。
oft:AQW 内存的第 oft 个 通道,0--AQW0
2--AQW2 奇数无效 Data:要更新的值
Err:存放返回的错误码
0--无错
其它--访问出错无U8 STL_SI(U32 byteOffset, U8 bitOffset, U8
pointNum)
(CTH300 系列 PLC 专用)
STL 中的 S(I 立即输出
1)指令
ByteOffset:字节偏移
bitOffset:位偏移 pointNum:位个数
返回错误码0--无错误其他--有错误。U8 STL_RI(U32 byteOffset, U8 bitOffset, U8
pointNum)
(CTH300 系列 PLC 专用)
STL 中的 R(I 立即输出
1)指令
ByteOffset:字节偏移
bitOffset:位偏移 pointNum:位个数
返回错误码0--无错误其他--有错误。mc_readSetPos(U8
AxisId, FP64 *ppos)
(CTH300 系列 PLC 专用)
读取轴的当前设置位
置
AxisId:轴号Err 错误指针0--无错,其他--错误mc_readActPos(U8
AxisId, U16 *pErr)
(CTH300 系列 PLC 专用)
读取轴的当前实际位
置
AxisId:轴号pErr:错误指针0--无错其他--错误void _c_init_(void);
C 环境初始化,在
sm0.1 中调用,json 等
功能必须使用。
NULL NULL
void Eth_Print(const
char *format, );
网口打印函数,监听
UDP 端口 9999
- - 5.5 SFC
PLC编程系统78
SFC 为系统功能,是由 COTRUST 提供的具有特定功能的 FC,不允许用户编辑和查看。不同类型的 CPU 可能支持不同的功能,目前 COTRUST 发布的 SFC 有:SFC1:ct_lib1 的调用接口;
SFC2:ct_lib2 的调用接口;
支持 SFC 的 COTRUST CPU 类型见下表:
支持的 SFC CPU 类型
SFC1 H226L/H226M /H224---4K
H224X----24K
SFC1、SFC2
H226XL/H226XM/H228XL/M228IL/M228ML/M228SL-----24KH226IM/H226IL/H226IH-----64K
H31-01/H35-01/H32-01/H36-01/H52-10/H56-10-----64K
5.6 局部变量表
以下两种情况下可以使用局部变量:
您希望建立不引用绝对地址或全局符号的可移动子程序。
您希望使用临时变量(说明为 TEMP 的局部变量)进行计算,以便释放PLC内存。如果以上说明对您的情形不适用,您无须使用局部变量;您可以在符号表中定义符号数值,将所有的符号数值定义为全局变量。
您可以使用程序编辑器的局部变量表指定对个别子程序或中断程序唯一的变量。局部变量可用作传递至子程序并可用于增加子程序的移动性或重新使用子程序的参数。程序中的每个 POU 都有自己的局部变量表,配备 64 个字节的 L 内存。这些局部变量表允许您定义具有范围限制的变量:局部变量只在建立该变量的 POU 中才有效。相反,在每个POU中均有效的全局符号只能在符号表中定义。当您为全局符号和局部变量使用相同的符号名时(例如 INPUT1),定义局部变量的 POU 中的局部定义优先,全局定义用于其他POU。在局部变量表中赋值时,您指定说明类型(TEMP、IN、IN_OUT 或OUT)和数据类型,但不指定内存地址;程序编辑器自动在 L 内存区中为所有的局部变量指定内存位置。局部变量表符号地址分配会将一符号名与存储有关数据值的 L 内存地址关联。局部变量表不支持向符号名直接赋值的符号常数(这在符号表中是许可的)。
<提示> PLC 不会将局部变量数据值初始为零。您必须在程序逻辑中初始化您使用的局部变量。局部变量的变量类型
对局部变量赋值指定的类型取决于在其中赋值的 POU。主程序(OB1)、中断程序和子程序可使用临时(TEMP)变量。只有在执行块时,临时变量才可用,块执行完成后,临时变量可被覆盖。子程序也可使用调用参数(IN、IN_OUT、OUT)。
区域 说明
IN 调用 POU 提供的输入参数
IN_OUT 数值由调用 POU 提供的参数,由子程序修改,然后返回调用POU
OUT 返回调用 POU 的输出参数
STAT 静态数据(仅针对功能块(FB))
MagicWorks PLC 编程软件用户手册
79
TEMP 临时保存在局部数据堆栈中的临时变量。一旦 POU 完全执行,临时变量数值则无法再用。在两次 POU 执行之间,临时变量不保持其数值局部变量的数据类型
将局部变量作为子程序参数传递时,在该子程序局部变量表中指定的数据类型必须与调用POU中数值的数据类型相匹配。
举例:
您从 OB1 调用 SBR0,将称为 INPUT1 的全局符号用作子程序的输入参数。在 SBR0 的局部变量表中,您已经将一个称为 FIRST 的局部变量定义为输入参数。当 0B1 调用 SBR0 时,INPUT1 数值被传递至 FIRST。
INPUT1 和 FIRST 的数据类型必须匹配。
如果 INPUT1 是实数,FIRST 也是实数,则数据类型匹配。如果 INPUT1 是实数,但FIRST是整数,则数据类型不匹配,只有纠正了这一错误,程序才能编译。
检视/隐藏局部变量表
如果您将水平分裂条拉至程序编辑器窗口的顶部,则局部变量表不再显示,但仍旧存在。将分裂条下拉即可再次显示局部变量表。
如何在局部变量表中赋值
提示
• 在程序中使用局部变量之前,在局部变量表中赋值最为有效。在程序中使用符号名时,程序编辑器首先检查适当 POU 的局部变量表,然后检查符号表。如果符号名在这两处均未定义,程序编辑器则将之视为未定义的全局符号;此类符号用绿色波浪状下划线标明。程序编辑器不会自动重新读取局部变量表并对您的程序逻辑做出修正。如果您后来进行了定义该符号名的数据类型分配(在局部变量表中),则须以手动方式在该符号名前插入一个#符号,例如:#UndefinedLocalVar(在程序逻辑中)。
• 每个子程序调用的输入/出参数的最大限制是 16,如果您尝试下载的程序超过此限制,则超出的临时变量将不会被下载至 PLC 中。
如何输入第一个局部变量赋值
欲在局部变量表中赋值,请遵循以下步骤:
1)确保正确的 POU 在程序编辑器窗口中显示,如有必要,点击所需的POU 标记。(因为每个 POU 都有自己的局部变量表,您需要确保对正确的 POU 赋值)
2)如果局部变量表处于隐藏状态,下拉水平分裂条,显示局部变量表。3)为需要定义的变量选择具有正确说明类型的行,在“名称”域中为该变量键入一个名称。(如果您在 OB1 或中断程序中赋值,局部变量表只包含 TEMP 变量。如果您在子程序中赋值,局部变量表包含 IN、IN_OUT、OUT 和 TEMP 变量。)您不需要在局部变量表中的变量名前加#号。#号只用在程序代码中的局部变量前。提示
• 局部变量表可包含数字,下划线和中英文字符,不可以数字开头,不能包含扩展字符。• 局部变量表变量名被下载并存储于 CPU 内存中,使用较长的变量名可能减少用于存储程序的内存空间。
4)在“数据类型”域中点击鼠标指针,并使用列表框为局部变量选择适当的数据类型。<注释>
PLC编程系统80
·当您将局部变量指定为子程序的参数时,您必须保证为局部变量指定的数据类型不与子程序调用中使用的操作数发生冲突(请参阅上文中的数据类型检查)。
·为【名称】和【数据类型】域提供数值后,程序编辑器会自动为局部变量指定L 内存地址。如何在局部变量表中输入附加赋值
对于 OB1 和中断程序,局部变量表显示一组已被预先定义为 TEMP 变量的行。在OB1或中断程序中,只能使用这种说明类型。欲在表中增加更多行,只需点击最后一行中的一个单元格,然后使用 ENTER 键移过该行并向下移动,即自动生成一个新行。
对于子程序,局部变量表显示按照以下顺序预先定义说明类型的一组行:IN、IN_OUT、OUT和 TEMP。您不能改变该顺序。局部变量在该表中的顺序必须符合当您为子程序调用指令进行操作数赋值时对应的操作数顺序。如果您希望增加附加局部变量,选中一个现有行,单击鼠标右键选择【插入行】即可在表中插入新行。
5.7 程序块的导入导出
导入程序块文件
选择菜单项【文件】→【导入】打开如下对话框,即可将 ASCII 文件格式的程序块文件(后缀为.awl)内容导入到当前激活的程序块文件。
导出程序块文件
选择菜单项【文件】→【导出】打开如下对话框,将当前程序块文件的内容以ASCII 文件格式导出到后缀为.awl 的文本文件。
MagicWorks PLC 编程软件用户手册
81
查看 ASCII 文本文件格式的一种简单方法是导出一个现有程序,然后使用Windows Notepad(记事本)编辑器检查文件内容。
如果导入 ASCII 文本文件(例如,test.awl)因语法错误失败,程序编辑器会以对话框的形式弹出提示。如果文件通过语法测试,则被添加至项目。因为 LAD 和FBD 编辑器不能显示行注释,因此导入文件中的注释会丢失。
导入初始化数据页文件
将 ASCII 文件格式的初始化数据页文件(后缀.txt)内容导入到当前激活的初始化数据页子窗口。
PLC编程系统82
5.8 交叉引用表
使用以下方式打开交叉引用表:
在项目管理器的项目树中选中交叉引用结点,即可看到右边的工作窗口中出现调用结构、交叉引用、字节引用、位使用、沿使用五个图标,双击其中一个图标或者在图标上单击鼠标右键选择【打开】菜单项即可启动交叉引用查看器并显示相应表页。
交叉引用查看器是多文档窗口,使用交叉引用查看器窗口菜单中的排列窗口菜单项或是选择其中的已打开窗口列表菜单项切换表页。
<注意> 必须执行程序编译后才能查看【交叉引用】表。
交叉引用表
当您想了解程序中使用了哪些符号名或存储区赋值时,可使用【交叉引用】表。【交叉引用】表列出在程序中使用的全部操作数,并指出它所在的位置(POU、网络或行位置)以及每次使用时的指令上下文。
名称 功能描述
元素 程序中已经使用的某一符号名或绝对地址
块 符号或地址所在的程序块
位置 符号或地址所在某程序块的网络与行描述的位置
关联
显示该符号或地址相关联的指令,相当于显示某具体位置行的程序语句中以该符号或地址为操作数的指令。
LAD 交叉引用示例:
MagicWorks PLC 编程软件用户手册
83
STL 交叉引用示例:
字节使用表
【字节使用】表允许您查看程序中使用了哪些字节以及在哪里使用的,您可借此检查程序中重复赋值错误。
b:表示已经使用存储区的一个位。
B:表示已经使用存储区的一个字节。
W:表示已经使用存储区的一个字。
D:表示已经指定存储区的一个双字。
X:用于定时器和计数器类型。
字节使用示例:
如下图所示,程序中使用了地址 VD0,SM0.X 和 SMB34:
PLC编程系统84
可通过检查字节使用表,识别重复的赋值。在适当的程序赋值中,字节/字/双字的标记应该是连续的,中间不会有不同的标记。如 DDwb 表示有重复赋值,而 DDDD 则没问题。如下面的程序中存在重复赋值:
编译后就会出现下面的字节使用表:
位使用表
位使用表允许您查看程序中已经使用了哪些位及在哪里使用的,您可借此检查程序中重复赋值错误。
b:表示已经使用存储区的一个位。
B:表示已经使用存储区的一个字节。
W:表示已经使用存储区的一个字。
D:表示已经指定存储区的一个双字。
X 用于定时器和计数器类型。
位使用示例:
如下图所示,程序中使用了地址 Q0.0 和 Q1.1
MagicWorks PLC 编程软件用户手册
85
可通过检查位使用表,识别重复的赋值。在适当的程序赋值中,字节/字/双字的标记应该是连续的,中间不会有位值标记。如 BBBBBBBb 表示有重复赋值,而 BBBBBBBB 没问题。例如:下面的程序中存在重复赋值:
编译后就会出现下面的位使用表:
沿使用表
沿使用表允许您查看程序中已经使用的沿指令的 ID,有助于您在线编辑时查找沿指令ID重复使用错误。
沿使用示例:由下图可知,程序中使用了 ID 为 0 和 50 的上升沿指令和ID 为1 的下降沿指令。
PLC编程系统86
调用结构
调用结构允许您查看程序中各个块之间的调用和被调用关系。
5.9 向导的使用
向导文件夹 用来存储当前版本支持的向导图标,用户可以通过点击项目树的向导结点打开向导文件夹来查看。当前支持的向导见下表:
指令向导
PID 支持
NETR/W-PPI 支持,每条读写 200 字节。
NETR/W UDP 支持
MODBUS-TC
P 支持
HSC 支持
PTO 支持
文本显示向导 支持 TD200 3.0 版,支持 TD400 1.0 和2.0 版。配方向导 支持
数据记录向导 支持
5.9.1 NETR/W-PPI 指令向导
【NETR/W-PPI 指令向导】可以创建项目代码,用于实现网络中的两个PLC 之间的数据交互。欲使用 NETR/W-PPI 指令向导,请遵循以下基本步骤:
1)选择菜单命令【工具】→【NETR/W-PPI 指令向导】或点击项目树中的向导结点,在右边的工作区域双击 NETR/W-PPI 向导图标 ,启动 NETR/W-PPI 指令向导。并随后打开此向导或某现有配置。
2)点击【下一步】按钮前往 NETR/W-PPI 向导的每个新页。
3)完成向导中的步骤后,点击【完成】按钮。
具体操作步骤如下:
MagicWorks PLC 编程软件用户手册
87
<第 1 步> 选择 PPI 通信端口进行网络读写操作,指定要配置的网络操作数:在对话框【您希望配置多少项 PPI 网络读(写)操作?】中设定要配置的网络操作数,目前允许的操作数范围是 1~24。
<第 2 步> 现在需要指定使用的通信端口和生成的功能名称:
在此页面中你可以更改以下信息:
1)作为 PPI 主站的 PLC 使用哪一个通信端口(PPI 通信口)与 PPI 从站进行通信。2)编辑向导生成的功能符号名。配置完成后,向导会建立一个用于执行具体网络操作的以此为名的参数化功能。
<第 3 步> 配置网络操作
PLC编程系统88
网络操作要配置的信息包括:
1)此操作是网络读还是写
2)从从站读入或写入从站多少个字节
3)要交互的 PLC 从站地址
4)本地 PLC 地址映射(只能是 V 内存),即读回的数据或待写入的数据存储在本地PLCV内存中的位置
此界面上三个按钮:
● 删除操作:删除当前的操作,此操作导致已配置的操作数目减一
● 上一个操作:将界面切换到上一个操作
● 下一个操作:将界面切换到下一个操作
<第 4 步> 分配 V 存储区
MagicWorks PLC 编程软件用户手册
89
对于您配置的每一项网络操作,要求有 12 个字节的 V 存储区。在此页中您可以选择想要存放该配置块的 V 内存地址。如果您希望向导建议正确大小的未使用内存块地址,则点击【建议地址】按钮。
<第 5 步> 生成项目组件
最后一步,指令向导将为您指定的配置生成相关的程序组件,包括: 网络读写符号表,包含配置中每个操作每个网络读写操作的状态符号地址。 功能 NET_EXE 包含了操作的具体代码,要在程序中使能网络通信,需要在主程序块中调用执行功能功能(NET_EXE)。每次扫描周期时,使用 SM0.0 调用该功能。这样会启动配置网络操作执行。为每项网络操作建立的数据处理功能会在适当时间被自动调用。PPI 向导生成的功能为具体操作指令,具体指令说明如下表所示:
PLC编程系统90
PPI 通信指令
指令名称 功能块图
NETRWPPI_EXE
符号 变量类型 数据类型 注释EN IN BOOL 使用 SM0.0 调用
Timeout IN INT 0 = 不计时;1-32767 = 计时值(秒)。Cycle OUT BOOL 每周期处理完所有的通信操作时置位。Error OUT BOOL
0 = 无错误;1 = 出错 (检查 NETR/W-PPI 指令缓冲区状态字节以获取错误代码)。
ErrorStep OUT BYTE 发生错误的操作步。
ErrorCode OUT BYTE
错误详情:
0 无错
1 超时错误,远程站不应答
2 接收错误,应答中存在校验、帧或校验和错误3 脱机错误,重复站地址或故障硬件引起的冲突4 队列溢出错误,8 个以上 NETR/NETW指令被激活5 违反协议,未启用 SMB30/SMB130 将端口设为PPI 主站模式即尝试执行 NETR/NETW
6.非法参数,NETR/NETW 表格包含一个非法或无效数值7 无资源,远程站繁忙(正在上载或下载序列)8 层 7 错误,违反应用程序协议9 信息错误,数据地址或数据长度不正确要在程序中执行 PPI 向导配置的网络操作,您需要在主程序块中使用SM0.0 调用该功能(NETRWPPI_EXE)。该功能在编程软件中的调用示例如下图所示:对于本说明中配置生成的功能,相关 PPI 通信操作如下表所述:
操作步 本地 PLC 数据表位置 远程设备操作状态存储位置数据长度写操作 VB0-VB1 -> VB0-VB1 NETR1_Status:VB46 2 Bytes
MagicWorks PLC 编程软件用户手册
91
读操作 VB2-VB3 <- VB0-VB1 NETR2_Status:VB55 2 Bytes通过状态监控表查看配置的各项操作的执行状态时,请参考下面的 UDP 网络读写操作状态字节定义表:
位编号 定义 说明
1 D 完成(功能完成)位,0 = 未完成,1 = 完成;2 A 激活位,指令正在执行中为 1,不在执行中为0;3 E 错误状态位,0 = 无错,1 = 有错误;
4 n4 保留,始终为 0;
5~8 错误代码 详细代码说明请参见本通信指令注释;
<注意> PPI 通信采用普通网络读写,执行读写操作时可组态多种寄存器,从站地址映射为直接映射方式。
5.9.2 NETR/W-UDP 指令向导
【NETR/W UDP 指令向导】可以创建项目代码,用于实现网络中的两个PLC 之间的数据交互。欲使用 NETR/NETW 指令向导,请遵循以下基本步骤:
1)选择菜单命令【工具】→【NETR/W-UDP 指令向导】或点击项目树中的向导结点,在右边的工作区域双击 NETR/W-UDP 向导图标 ,启动 NETR/W-UDP 指令向导。并随后打开此向导或某现有配置。
2)点击【下一步】按钮前往 NETR/W-UDP 向导的每个新页。
3)完成向导中的步骤后,点击【完成】按钮。
具体操作步骤如下:
<第 1 步> 选择以太网通信端口进行网络读写操作,指定要配置的网络操作数:




