1、第4章 S7-1200的用户程序结构4.1 函数与函数块函数与函数块 4.1.1 生成与调用函数生成与调用函数 1函数的特点函数的特点 函数FC和函数块FB是用户编写的子程序,它们包含完成特定任务的程序,FC和FB有与调用它的块共享的输入、输出参数。设压力变送器量程的下限为0MPa,上限为High MPa,经A/D转换后得到027648的整数。转换后的数字N和压力P之间的计算公式为P=(High N)/27648 (MPa)用函数FC1实现上述运算。2生成函数生成函数 双击指令树的“添加新块”,单击“添加新块”对话框中的“函数”按钮,FC默认的编号为1,默认的语言为LAD。设置函数的名称为“计
2、算压力”。单击“确定”按钮,生成FC1。3定义函数的局部数据定义函数的局部数据 往下拉动程序区最上面的分隔条,分隔条上面是函数的接口区,下面是程序区。在接口区中生成局部变量,后者只能在它所在的块中使用。右键单击项目树中的FC1,单击快捷菜单中的“属性”,选中打开的对话框左边的“属性”,用复选框取消默认的属性“块的优化访问”。成功编译后接口区出现“偏移量”列,只有临时数据才有偏移量。函数各种类型的局部变量的作用如下:1)输入参数Input用于接收调用它的块提供的输入数据。2)输出参数Output用于将块的程序执行结果返回给调用它的块。3)输入_输出参数InOut的初值由调用它的块提供,块执行完后
3、用同一个参数将它的值返回给调用它的块。4)文件夹Return中自动生成的返回值“计算压力”与函数的名称相同,属于输出参数。数据类型为Void,表示函数没有返回值。函数还有两种局部数据:5)临时数据Temp是暂时保存在局部数据堆栈中的数据。每次调用块之后,临时数据可能被同一优先级中后面调用的块的临时数据覆盖。6)常量Constant是块中使用并且带有符号名的常量。4FC1的程序设计的程序设计 程序见下图,运算的中间结果用临时局部变量“中间变量”保存。STEP 7自动地在局部变量的前面添加#号。5在在OB1中调用中调用FC1 在变量表中生成调用FC1时需要的3个变量,将项目树中的FC1拖放到右边的
4、程序区的水平“导线”上。FC1的方框中左边的“输入数据”等是在FC1的接口区中定义的输入参数和输入/输出参数,右边的“压力值”是输出参数。它们被称为块的形式参数,简称为形参,形参在FC内部的程序中使用。方框外是调用时为形参指定的实际参数,简称为实参。实参与它对应的形参应具有相同的数据类型。STEP 7自动地在全局变量的符号地址两边添加双引号。PLC变量表 OB1调用FC1的程序 6函数函数应用的实验应用的实验 将程序下载到仿真CPU后,CPU切换到RUN模式。单击精简视图右上角的 按钮,切换到项目视图。生成一个新的项目,双击打开“SIM表格_1”。在表中生成下图中的条目。令I0.6为1状态,调
5、用FC1,令IW64为13824(27648的一半),执行FC1中的程序后,输出参数“压力值”的值5.0 MPa被传送给它的实参“压力计算值”MD18。4.1.2 生成与调用函数块生成与调用函数块 1函数块函数块 函数块(FB)是用户编写的有自己的存储区(背景数据块)的代码块,FB的典型应用是执行不能在一个扫描周期结束的操作。每次调用函数块时,都需要指定一个背景数据块。2生成函数块生成函数块 在项目“函数与函数块”中添加名为“电动机控制”的FB1。取消FB1默认的属性“块的优化访问”。3定义函数块的局部变量定义函数块的局部变量 函数块的输入、输出参数和静态数据用指定的背景数据块保存。在FB中,
6、定时器如果使用一个固定的背景数据块,在同时多次调用该FB时,该数据块将会被同时用于两处或多处。为此在块接口中生成数据类型为IEC_TIMER的静态变量“定时器DB”,用它提供定时器TOF的背景数据。4FB1的控制要求与程序的控制要求与程序 用输入参数“起动按钮”和“停止按钮”控制InOut参数“电动机”。按下停止按钮,断开延时定时器(TOF)开始定时,输出参数“制动器”为1状态,经过输入参数“定时时间”设置的时间预置值后,停止制动。在TOF定时期间,每个扫描周期执行完FB1之后,用静态变量“定时器DB”来保存TOF的背景数据。可以修改函数块的输入、输出参数和静态变量的默认值。该默认值作为FB的
7、背景数据块同一个变量的起始值。调用FB时没有指定实参的形参使用背景数据块中的起始值。5用于定时器计数器的用于定时器计数器的多重背景多重背景 IEC定时器指令实际上是函数块,每次调用它们时,都需要指定一个背景数据块。为了解决前述的FB中定时器、计数器固定的背景数据块带来的问题,在函数块的接口区定义数据类型为IEC_Timer的静态变量(见图4-6),用它们来提供定时器和计数器的背景数据。这种程序结构被称为多重背景。将定时器TON方框拖放到FB1的程序区,出现“调用选项”对话框。单击选中“多重实例”,选中列表中的“定时器DB”,用FB1的静态变量“定时器DB”提供TON的背景数据。这样处理后,多个
8、定时器、计数器的背景数据被包含在它们所在的函数块的背景数据块中,不需要为每个定时器或计数器设置一个单独的背景数据块。6在在OB1中调用中调用FB1 在PLC默认变量表中生成两次调用FB1使用的符号地址。在OB1中两次调用FB1,自动生成背景数据块。为各形参指定实参。7调用函数块的调用函数块的仿真实验仿真实验 将程序下载到仿真PLC,后者进入RUN模式。在S7-PLCSIM的项目视图,生成一个新的项目,打开“SIM表格_1”,生成IB0和QB0的SIM表条目。两次单击起动按钮 I0.0,1号设备Q0.0变为1状态。两次单击停止按钮I0.1,Q0.0变为0状态,制动 Q0.1变为1状态。经过参数“
9、定时时间”设置的时间后Q0.1变为0状态。可以令两台设备几乎同时起动、同时停车和制动延时。8处理调用错误处理调用错误 调用符号名为“电动机控制”的FB1之后,在FB1的接口区增加了输入参数“定时时间”,被调用的FB1的字符变为红色。右键单击出错的FB1,执行快捷菜单中的“更新块调用”命令,出现“接口同步”对话框,显示出原有的块接口和增加了输入参数后的块接口。单击“确定”按钮,“接口同步”对话框消失。被调用的FB1被修改为新的接口,程序中FB1的红色字符变为黑色。9函数与函数块的区别函数与函数块的区别 FB和FC均为用户编写的子程序,接口区中均有Input、Output、InOut参数和Temp
10、数据。FC的返回值实际上属于输出参数。下面是FC和FB的区别:1)函数块有背景数据块,函数没有。2)只能在函数内部访问它的局部变量。其他代码块或HMI可以访问函数块的背景数据块中的变量。3)函数没有静态变量,函数块有保存在背景数据块中的静态变量。如果函数或函数块的内部不使用全局变量,只使用局部变量,不需要做任何修改,就可以将块移植到其他项目。如果代码块有执行完后需要保存的数据,应使用函数块。4)在调用函数块时可以不设置某些输入、输出参数的实参,而是使用它们的默认值。函数的局部变量没有默认值,调用时应给所有的形参指定实参。5)函数块的输出、输入参数和用静态数据保存的内部状态数据有关。10组织块与
11、组织块与FB和和FC的区别的区别 出现事件或故障时,由操作系统调用对应的组织块,FB和FC是用户程序在代码块中调用的。组织块没有输出参数、InOut参数和静态数据,它的输入参数是操作系统提供的启动信息。用户可以在组织块的接口区生成临时变量和常量。组织块中的程序是用户编写的。4.1.3 多重背景多重背景 在项目“多重背景”中生成与4.1.2节相同的名为“电动机控制”的函数块FB1,去掉FB1“优化的块访问”属性。生成一个名为“多台电动机控制”的函数块FB3,去掉FB3“优化的块访问”属性。在它的接口区生成两个数据类型为“电动机控制”的静态变量“1号电动机”和“2号电动机”。每个静态变量内部的参数
12、是自动生成的,与FB1“电动机控制”的相同。在FB3中调用FB1,在“调用选项”对话框中选中“多重实例DB”,选中列表中的“1号电动机”,用FB3的静态变量“1号电动机”提供FB1“电动机控制”的背景数据。用同样的方法调用FB1来控制2号电动机。在OB1中调用FB3“多台电机控制”,FB3的背景数据块只有静态变量“1号电动机”和“2号电动机”。在这个例子中实际上有3重背景数据。FB3的背景数据块DB3包含了两次调用FB1的背景数据,后者又包含了定时器TOF的背景数据。将用户程序下载到仿真PLC,CPU切换到RUN模式。生成一个新的项目,在SIM表格_1中生成地址IB0和QB0,用I0.0和I0
13、.2分别启动1号、2号电动机,用I0.1和I0.3分别停止1号、2号电动机,观察电动机和制动器的状态变化是否正常。FB3OB14.2 数据类型与间接寻址数据类型与间接寻址4.2.1 数据类型数据类型 1数据类型的分类数据类型的分类 数据类型分为基本数据类型、复杂数据类型、参数类型、系统数据类型和硬件数据类型。(1)参数类型 参数类型是传递给被调用块的形参的数据类型。参数类型Void不保存数值,它用于函数不需要返回值的情况。(2)系统数据类型 系统数据类型(SDT)由系统提供,可供用户使用,具有不能更改的预定义的结构。例如定时器结构IEC_TIMER,6种整数数据类型的计数器结构等。(3)硬件数
14、据类型 硬件数据类型与硬件组态时模块的设置有关。它用于识别硬件元件、事件和中断OB等与硬件有关的对象。PLC变量表的“系统常量”选项卡列出了项目中的硬件数据类型变量的值,即硬件组件和中断事件的标识符。2数据类型的转换方式数据类型的转换方式 调用指令或块时,如果操作数具有不同的数据类型,应对它们进行转换。(1)隐式转换 如果操作数的数据类型兼容,将自动执行隐式转换。兼容性测试使用两种标准:1)默认的是IEC检查,采用严格的兼容性规则,允许转换的数据类型较少。2)不进行IEC检查,兼容性测试采用不太严格的标准,允许转换的数据类型较多。(2)显式转换 操作数不兼容时,只能使用显式转换指令。可使用指令
15、列表的“数学函数”“转换操作”和“字符串+字符”文件夹中的指令进行转换。3设置设置IEC检查功能检查功能 (1)设置对项目中所有新的块进行IEC检查 执行“选项”菜单中的“设置”命令,选中出现的“设置”编辑器左边窗口的“PLC编程”中的“常规”组,用复选框选中右边窗口“新块的默认设置”区中的“IEC检查”。(2)设置单独的块进行IEC检查 如果没有作上述的设置,右键单击项目树中的某个代码块,执行快捷菜单中的“属性”命令,选中打开的对话框左边窗口的“属性”组,用右边窗口中的复选框激活或取消IEC检查功能。4.2.2 间接寻址间接寻址 1用用FieldRead与与FieldWrite指令实现间接寻
16、址指令实现间接寻址 打开项目“间接寻址”,在DB1中生成了“数组1”Array1.5 of Int。用指令FieldRead(读取域)和FieldWrite(写入域)指令实现间接寻址。设置要写入或读取的数据类型为Int。参数MEMBER的实参必须是数组的第一个元素“数据块1”.数组11。参数索引值“INDEX”是要读写的数组元素的下标,数据类型为DINT。参数“VALUE”是要写入数组元素的操作数或保存读取的数组元素的值的地址。将程序下载到仿真PLC,启动OB1的程序状态监视功能。用鼠标右键单击实参MD10,将它的值修改为3。启用数据块1的监视功能,可以看到输入参数VALUE的值25被写入下标
17、为3的数组元素“数据块1”.数组13。修改INDEX的值,VALUE的值将被写入INDEX对应的数组元素。用上述方法设置MD14的值为3,输出参数VALUE的实参MW18中是读取的下标为3的数组元素“数据块1”.数组13的值。2使用使用MOVE指令的间接寻址指令的间接寻址 在MOVE指令中使用变量作数组的下标可以实现间接寻址。可以用多个变量作多维数组的下标,实现多维数组的间接寻址。修改下图中的“下标3”(MD30),就可以改写数据块1.数组2中不同下标的元素的值。修改下图中的“下标4”(MD34),就可以读取数据块1.数组2中不同下标的元素的值。如果变量“下标3”或“下标4”的值超出数组2定义
18、的范围,出现区域长度错误,CPU的ERROR LED将会闪烁。3使用间接寻址的循环程序使用间接寻址的循环程序 在项目“间接寻址”的DB1中生成有5个DInt元素的数组“数组2”,数据类型为Array1.5 of DInt,设置各数组元素的初始值。生成一个名为“累加双字”的函数FC1,输入参数“数组IN”的数据类型为Array1.5 of Dint。FC1的程序首先将“累加结果”清零,设置数组下标的初始值为1,程序段2的跳转标签Back表示循环的开始。指令FieldRead用来实现间接寻址,其参数INDEX是要读写的数组元素的下标。读取数组元素值后,将它与输出参数“累加结果”的值相加,将数组的下
19、标加1,它指向下一个数组元素,为下一次循环做好准备。将作为循环次数计数器的“累加个数”减1。减1后如果非0则返回标签Back处,开始下一次循环的操作。在OB1中调用FC1“累加双字”,求数据块1中的数组2从第一个元素开始,若干个数组元素之和,运算结果用MD20(“累加值”)保存。将程序下载到仿真PLC,CPU切换到RUN模式。用MW24设置要求和的数组元素的个数为5。启动监视功能。在“累加启动”信号M2.0的上升沿调用FC1“累加双字”,通过循环程序计算出数组2的5个元素的累加和为15。4.3 中断事件与中断指令中断事件与中断指令4.3.1 事件与组织块事件与组织块 1启动组织块的事件启动组织
20、块的事件 组织块OB是操作系统与用户程序的接口,出现启动组织块的事件时,由操作系统调用对应的组织块。如果当前不能调用该OB,则按照事件的优先级将其保存到队列。如果没有为该事件分配OB,则会触发默认的系统响应。2事件执行的优先级与中断队列事件执行的优先级与中断队列 事件一般按优先级的高低来处理,先处理高优先级的事件。优先级相同的事件按“先来先服务”的原则来处理。如果设置为OB可中断模式,更高优先级的事件将中断正在运行的OB。各事件有默认的组织块,此外还可以生成编号大于等于123的组织块。3延时执行较高优先级中断和异步错误事件延时执行较高优先级中断和异步错误事件 可以用指令DIS_AIRT延时处理
21、优先级高于当前组织块的中断OB,用指令EN_AIRT启用以前调用DIS_AIRT延时的组织块处理。4.3.2 初始化组织块与循环中断组织块初始化组织块与循环中断组织块 1程序循环组织块程序循环组织块 项目为“启动组织块与循环中断组织块”,程序循环组织块OB1是自动生成的。双击项目数中的“添加新块”,单击“组织块”按钮,选中列表中的“Program cycle”,生成一个程序循环组织块。OB默认的编号为123,语言为LAD。单击“确定”按钮,生成OB123。分别在OB1和OB123中生成简单的程序,将它们下载到仿真PLC,如果可以用I0.4和I0.5分别控制Q1.0和Q1.1,说明OB1和OB1
22、23均被循环执行。2启动组织块启动组织块 启动组织块用于首次扫描时将系统初始化,生成OB100,给QB0置初值7,将MB14加1。在仿真时观察OB100的功能是否正常。3循环中断组织块循环中断组织块 循环中断组织块以设定的循环时间(160000ms)周期性地执行,而与程序循环OB的执行无关。循环中断和延时中断组织块的个数之和最多允许4个,循环中断OB的编号应为OB30OB38,或大于等于123。生成OB30,将循环时间改为1s。相位偏移用于错开不同时间间隔的几个循环中断OB。OB30的程序控制8位彩灯循环移位,I0.2控制彩灯是否移位,I0.3控制移位的方向。在CPU运行期间,用SET_CIN
23、T指令重新设置循环中断的循环时间和相移,时间的单位为s,用QRY_CINT指令查询循环中断的状态。MB9是读取的状态字MW8的低位字节,M9.4为1表示已下载OB30,M9.2为1表示已启用循环中断。4.3.3 时间中断组织块时间中断组织块 时间中断用于在设置的日期和时间产生一次中断,或从设置的日期时间开始,周期性地重复产生中断。时间中断OB的编号应为1017,或大于等于123。在OB1中调用指令QRY_TINT来查询时间中断的状态。在I0.0的上升沿,调用指令SET_TINT和ACT_TINT来分别设置和激活时间中断OB10。参数LOCAL为1表示使用本地时间。16#0201表示每分钟产生一
24、次时间中断。参数ACTIVATE为1时,该指令设置并激活时间中断,为0仅设置时间中断。本例用指令ACT_TINT来激活时间中断。在OB10中将MB4加1。打开仿真软件S7-PLCSIM,生成一个新的项目,生成IB0、MB4和MB9的SIM表条目,MB9是QRY_TINT读取的状态字MW8的低位字节。下载所有的块后,仿真PLC切换到RUN模式,M9.4为1状态,表示已经下载了OB10。M9.2为1状态,表示时间中断已被激活。如果设置的是已经过去的日期和时间,CPU将会在0秒时每分钟调用一次OB10,将MB4加1。在I0.1的上升沿,时间中断被禁止,M9.2变为0状态,MB4停止加1。在I0.0的
25、上升沿,时间中断被重新激活,M9.2变为1状态,MB4每分钟又被加1。4.3.4 硬件中断组织块硬件中断组织块 硬件中断事件包括CPU内置的和信号板的DI的上升沿/下降沿事件,高速计数器的实际计数值等于设定值、计数方向改变和外部复位输入信号的上升沿。最多可以生成50个硬件中断OB,其编号应为4047,或大于等于123。在项目“硬件中断例程1”中生成硬件中断OB40、OB41,组态时将它们分配给I0.0的上升沿事件和I0.1的下降沿事件。在OB40和OB41中,分别用M1.2一直闭合的常开触点将Q0.0:P置位和复位。将程序下载到仿真PLC,生成一个新的仿真项目,打开SIM表格_1,生成IB0和
26、QB0的SIM表条目。两次单击I0.0对应的小方框,在I0.0的上升沿,CPU调用OB40,将Q0.0置位为1。两次单击I0.1对应的小方框,在I0.1的下降沿,CPU调用OB41,将Q0.0复位。4.3.5 中断连接指令与中断分离指令中断连接指令与中断分离指令 “将OB附加到中断事件”指令ATTACH和“将OB与中断事件分离”指令DETACH分别用于在PLC运行时建立和断开硬件中断事件与中断OB的连接。要求使用指令ATTACH和DETACH,在出现I0.0上升沿事件时,交替调用硬件中断组织块OB40和OB41,分别将不同的数写入QB0。项目为“硬件中断2”。在硬件组态时将OB40分配给I0.
27、0的上升沿中断事件。该中断事件出现时,调用OB40。在OB40中,断开该事件与OB40的连接,建立该事件与OB41的连接。用MOVE指令给QB0赋值为16#F。OB40 下一次出现I0.0上升沿事件时,在OB41中,断开该事件与OB41的连接,建立该事件与OB40的连接。用MOVE指令给QB0赋值为16#F0。OB41 将程序下载到PLC,生成一个新的仿真项目,打开仿真表,生成I0.0和QB0的SIM表条目。在I0.0的上升沿,CPU调用OB40,断开I0.0的上升沿事件与OB40的连接,将该事件与OB41连接。将16#0F写入QB0,后者的低4位为1。在I0.0下一个上升沿,CPU调用OB4
28、1,断开I0.0的上升沿事件与OB41的连接,将该事件与OB40连接。将16#F0 写入QB0,后者的高4位为1。连续多次单击I0.0对应的小方框,CPU交替调用OB40和OB41,QB0被交替写入16#0F和16#F0。4.3.6 延时中断组织块延时中断组织块 延时中断OB的编号为2023,或大于等于123。项目为“延时中断例程”。在I0.0的上升沿中断OB40中,调用指令SRT_DINT,启动10s延时。时间范围为160000ms,精度为1ms。调用“读取本地时间”指令RD_LOC_T,读取启动延时的时间,用DB1中的变量DT1保存。定时时间到时调用OB20。在OB20中用RD_LOC_T
29、指令读取延时结束的时间,用DB1中的变量DT2保存。同时将Q0.4:P置位。OB40OB20 在OB1中调用指令QRY_DINT来查询延时中断的状态字STATUS。在I0.1为1时调用指令CAN_DINT来取消延时中断过程。仿真时生成IB0、QB0和MB9的SIM表条目,M9.4为1表示OB20已经下载到CPU,M9.2为1表示正在执行SRT_DINT启动的时间延时。监控DB1中延时的起、止时间。定时期间令I0.1为1状态,调用指令CAN_DINT取消时间延迟,M9.2变为FALSE。10s的延迟时间到的时候,不会调用OB20,Q0.4不会变为TRUE,DB1中的DT2也不会显示出新读取的时间
30、值。OB14.4 交叉引用表与程序信息交叉引用表与程序信息4.4.1 交叉引用表交叉引用表 交叉引用表提供用户程序中操作数和变量使用情况的概览。可以从交叉引用表获取某个操作数在程序中何处使用;某个变量被用于HMI哪个画面中的哪个元件;某个块被哪些块调用等。在项目视图中,可以生成PLC文件夹、程序块文件夹、单独的块、PLC变量表和单独的变量的交叉引用。可用工具栏上的按钮、右键命令、“工具”菜单中的 命令生成和显示交叉引用表。例:生成项目“PLC_HMI”的“默认变量表”的交叉引用表。可以看到变量“电动机”在主程序Main和HMI的根画面的被引用的情况。“引用类型”列的“使用者”表示源对象“电动机
31、”被对象Main和“圆_1”使用。该列中的“使用”表示源对象“电动机”使用了对象“HMI_连接_1”。“作为”列是被引用对象更多的信息,“访问”列是访问的读、写类型,“地址”列是操作数的绝对地址,“类型”列是创建对象时使用的类型和语言,“路径”列是项目树中该对象的路径以及文件夹和组的说明。蓝色字符表示有链接,单击它打开对应的编辑器,光标选中有关的对象。选中程序区或变量表中的某个变量,在下面的巡视窗口的“信息 交叉引用”选项卡,可以看到它的交叉引用信息。选中项目树中的Main,单击工具栏上的交叉引用 按钮,生成Main的交叉引用表。4.4.2 分配列表分配列表 分配列表提供I、Q、M存储区的字节
32、中各个位的使用情况。打开项目“数据处理指令应用”,右键单击“程序块”文件夹,执行菜单命令“分配列表”。单击“位存储器”左边的按钮,可显示分配列表中的图形符号列表。可用按钮显示和设置M区的保持功能。带眼睛的按钮打开的复选框可设置是否显示“已使用的地址”和“空闲的硬件地址”。可以用过滤器来“过滤”分配列表显示的内容。4.4.3 调用结构、从属性结构与资源调用结构、从属性结构与资源 调用结构显示用户程序中块与块之间调用与被调用的关系的体系结构。右键单击项目“1200_1200ISO_C”的项目树中的程序块文件夹,执行菜单命令“工具”“调用结构”。单击“详细信息”列,可以看到指定的块被调用的详细情况。调用结构的第一层是组织块,下一层的块是被调用的块。定时器计数器指令实际上是函数块,在调用结构中不会显示它们。从属性结构是块在用户程序中被使用的情况的列表。下图是例程“函数与函数块”的从属性结构。块在第一级显示,调用或使用它的块在它的下面向右后退若干个字符。选中程序块文件夹或其中的块,执行菜单命令“工具”“从属性结构”,将显示选中的PLC的从属性结构。资源用于显示CPU的硬件资源,各种存储器的最大存储空间和已使用的字节数,各OB、FC、FB、DB等占用的存储器的详细情况。以及已组态和已使用的DI、DO、AI、AO的点数。