西门子PLC S7-1200 Step7 V12学习体会

分享到:
13430
下一篇 >

江湖小虾分享:

西门子S7-1200发布后,并未太加以注意,因市场低端与中端分别是S7-200与S7-300的天下,也并未在工程项目中投入使用。直到不久前,因无法忍受X系,XX系,XXX系产品低效的编程模式(因客户要求,想在项目中用300都是一种奢望),上网一查资料,1200都功能这么完备了,当即开始折腾,装系统(Step 7 V12需操作系统在XP SP3及以上),装软件,一个多月下来,感觉收获挺大的,在这里跟大家分享一下,说得不好的,大家放心地踢吧!

1、1200学习三宝:软件,手册与电脑

软件:现在S7-1200编程软件版本都到Step7 V12 SP1了,而且此软件还可对300、400以及HMI等编程,建议使用Step7 V12,其在Step7 V11基础上有了很多改善,用来做项目完全适用且好用。如果不嫌麻烦,也可再安装Step 7 V12 SP1。

以上编程软件需要到西门子工业自动化英文网站下载,且需先注册,通过认证后才能下载,并且下载时有时**个文件及*后一个仿真程序不能下载。网上有提供BT下载的,我的另外一个贴子回复里有BT下载种子,链接:http://www.ad.siemens.com.cn/club/bbs/post.aspx?b_id=50&a_id=1053415&s_id=76&num=73&pno=4#anch


手册:必备以下手册:

1)S7-1200可编程控制器系统手册(12年4月版),链接:https://support.automation.siemens.com/CN/llisapi.dll?aktprim=0&lang=zh&referer=%2fCN%2f&func=cslib.csinfo&siteid=cseus&groupid=4000003&extranet=standard&viewreg=CN&&nodeid0=34612486&objaction=csopen

2)Step7 Professional V12.0系统手册,链接:https://support.automation.siemens.com/CN/llisapi.dll?query=step+7+professional+v12.0&func=cslib.cssearch&content=adsearch%2Fadsearch.aspx&lang=zh&siteid=cseus&objaction=cssearch&searchinprim=0&nodeid0=34612486&x=20&y=10

3)编程软件帮助文件:安装了Step 7 V12编程软件后,其帮助 文件非常给力,基本覆盖手册2内容,但内容检索等比手册2方便,但是只能在安装了Step 7 V12的电脑上使用。


电脑:虽然做项目大家都用笔记本电脑,但是现在笔记本电脑1366*768的分辨率且来编程的话还是小了点,屏幕上基本都没多少空间了,平时编程还是扩展一台24吋的显示器吧。


2、编程语言

我个人从开始学习S7-1200编程起就使用SCL进行编程,虽然SCL程序编译后代码量大一些,但以Step 7 V12编译器效率及CPU的工作存储器容量,做小型项目时不用担心工作内存不够的问题。

SCL语言属**语言,其编程思路更符合人的思维,程序较简洁,且不同PLC间项目移植容易,应是今后编程语言的发展方向。

-

从S7-300/400转到S7-1200时,很多人都会觉得间接寻址没有S7-300下STL编程时方便,因为S7-1200间接寻址是基于数组进行操作的(PEEK及POKE指令除外,关于S7-1200间接寻址下一篇进行说明)。

其实S7-1200提供了变量覆盖及变量部分引用(Slice引用)这一利器,使其在进行间接寻址时一点也不比S7-300差,特别是在SCL编程模式下更便利。

先看一下”变量覆盖“定义,Step 7 V12.0系统手册第2048页说明如下:“要访问声明变量内的数据区域,则可以通过附加声明来覆盖所声明的变量。 这样,可以选择对不同数据类型的已声明变量进行寻址。 例如,可以使用 BOOL 的 ARRAY 对 WORD数据类型变量的各个位寻址”。

简而言之,比如定义了一个word变量(假设变量名为wordTag1),然后对此变量进行覆盖,覆盖类型为Bool类型的数组,数组下标为0~15(假设覆盖变量名为atwordTag1,类型为Array[0..15] of Bool),则可使用该数组配合下标对该word变量的不同位进行间接寻址,如atwordTag1[i],当i=3时表示wordTag1的第3位,改变i的值即可对wordTag1不同位进行寻址。

S7-1200中,能够进行变量覆盖的块是FB或FC,但是有一些限制条件:

1)对于FC,必须设置属性为“标准块访问”,因创建FC时其默认访问属性为“优化的块访问”,必须更改访问属性并重新编译方可;

2)FC中只有Temp区变量可设置为结构化变量覆盖,即对基本型变量设置array或struct型覆盖变量(如上例中所示),对In,Out及InOut区基本型变量只能设置基本型覆盖变量,且长度要一致,实用意义不大;

3)对于FB,属性为“标准访问”或“优化访问”下均可进行变量覆盖,但有区别:标准访问下,可对所有接口参数区进行变量覆盖,只是InOut区对基本型变量只能设置基本型覆盖变量(但与FC下不同,其长度不必要求相同);在优化访问下,如果要对变量进行覆盖,必须将其保持性设置为“在IDB中设置”,这意味着Temp区变量将不能设置覆盖,其它与“标准访问”下无区别。

Step 7 V12中允许在创建块后对其访问属性进行更改,这意味着编程时不必纠结于块的访问属性,初始化设置为“优化访问”以节约资源,当需要进行变量覆盖时再变更其访问属性即可。


特别需要注意的是在FC中对In,Out及InOut区设置变量覆盖,以及对FB中InOut区设置变量覆盖时,只能使用基本型变量对基本型变量进行覆盖,否则编译时会出错,如下图所示,尽管书写程序时并无报警。





酱油甲:

为什么还喜欢用AT指令呢?从V11SP2后就可以直接读取啊!

比如定义一个变量Var_DInt0 : DInt ,那么

Var_DInt0.x0 到Var_DInt0.x31 就表示位0到位31

Var_DInt0.b0到Var_DInt0.b3 就表示字节0到字节3

Var_DInt0.w0和Var_DInt0.w1 就表示字0和字1


江湖小虾:

使用AT指令主要是为了取得类似“变址寻址”的效果,即通过改变数组下标值达到操作数据不同位的效果,在循环指令中比较有用,如下例,采用循环语句判断组0~9位是否有上升沿指令,如有则将另外2组相同位置零。
 


在S7-1200的tep7 V11的编程中,有3种方法实现间接寻址,分别是FieldRead / FieldWrite(适用于LAD编程)以及PEEK / POKE指令(适用于SCL编程),另有直接对数组下标变址寻址的间接寻址指令(适用于LAD/SCL编程)。

1) FieldRead及FieldWrite指令

此指令适用于LAD编程,且需预先定义数组,其通过改变数组下标实现读取或写入不同数组元素,从而实现间接寻址,例子下图所示。

先在DB1中建立1个Bool型数组arrayBool1[0..15] of Bool,即此数组中元素为Bool型,下标从0开始,共16个元素。





说明:1.1 可用于间接寻址的变量类型很多,可通过图中“FiledRead”处下拉框选择,未选择前此处显示“???”,选择后即为待读取的数组中元素类型,如上图,数组arrayBool1中元素类型为Bool;

1.2 输入“INDEX”为待读取的数组的下标,注意其可为常数或变量,若为变量,则该变量须为Dint型,否则会编译出错;

1.3 输入“MEMBER”为待读取数组的第1个元素,如数组下标从0开始,则此处须为arrayBool1[0],如若数组下标从-2开始,则此处须为arrayBool1[-2],否则会编译出错;

1.4 输出“VALUE”为读出数组中规定元素值后传送至此,即将此值写入VALUE中,此处要求其数据类型与读取的数组元素类型一致;

1.5 FieldWrite指令与此类似,为将VALUE值写入数组MEMBER[INDEX]中。


总结:FieldRead及FieldWrite需要配合数组进行操作以实现间接寻址,此指令在SCL编程时直接用数组下标来取值,如下所述。

2) SCL/LAD中MEMBER[INDEX]语句

在SCL或LAD编程时,可直接采用MEMBER[INDEX]语句,表示数组MEMBER的第INDEX个元素,实现简化间接寻址,如下两图所示,分别为SCL及LAD编程时采用数组下标间接寻址。



说明:2.1 #wordWelderDnSignalMap为FC的Output参数,#wordTemp为FC的word型Temp参数,  atTemp1为其变量覆盖(以Bool型数组覆盖),wordWelderDnSignal为FC的In参数;

2.2 下标index类型不限于Dint(LAD中需指定为Dint),此例中index类型为int;

2.3 可传送多种类型,只要保持数组中元素数据类型与待赋值变量数据类型一致即可。



如上图,利用MOVE指令传送数组元素。


3) PEEK / POKE指令(适用于SCL)

以上间接寻址均需要数组参与,如果想对非数组变量(如I,Q,M区的位,字节,字及双字变量)进行间接寻址,需使用PEEK及POKE指令。

3.1 PEEK指令

PEEK指令共有对Bool操作的PEEK_BOOL指令,对Byte操作的PEEK指令(默认),对字操作的 PEEK_WORD指令及对双字操作的PEEK_DWORD指令;

PEEK_BOOL指令有4个参数,其它PEEK指令参数为3个,如下图所示。



PEEK_BOOL指令参数说明如下:

area:定义读取数据存储区。16#81为I区,16#82为Q区,16#83为M区,16#84为DB区

dbNumber:定义DB编号,或area参数不为16#84,此值必须为0

byteOffset:定义欲读取的字节编号

bitOffset:定义欲读取的位编号

指令返回值:读取相应类型数据的结果

相对于PEEK_BOOL,其它PEEK指令除没有bitOffset参数外,余参数含义皆一致。



说明:第1条指令将M5.2数据写入数组变量arrayWelderInterlockStatus第1个元素中,数据为Bool型

第2条指令将MB4数据写入变量wordWelderInterlockStatus中,数据为Byte型


3.2 POKE指令

POKE指令共有3个:对Bool类型数据操作的POKE_BOOL指令;对字节,字及双字操作的POKE指令,以及对字节,字及双字批量写入的POKE_BLK指令。




POKE指令参数含义如下:

area:area:定义待写入数据存储区。16#81为I区,16#82为Q区,16#83为M区,16#84为DB区

dbNumber:定义DB编号,或area参数不为16#84,此值必须为0

byteOffset:定义待写入的字节编号

value:待写入数值

POKE_BOOL指令参数含义如下:

bitOffset:定义待写入的位编号

其它参数与POKE参数含义相同。

POKE_BLK指令参数含义如下:

area_src:源数据格式,16#81为I区,16#82为Q区,16#83为M区,16#84为DB区

dbNumber_src:定义源数据区DB编号,若源数据为DB区,则此值为0

byteOffset_src:定义源数据区字节编号

area_dest:目标数据格式,16#81为I区,16#82为Q区,16#83为M区,16#84为DB区

dbNumber_dest:定义目标数据区DB编号,若目标数据为DB区,则此值为0

byteOffset_dest:定义目标数据区字节编号

count:定义需传送的字节数

POKE指令一般不需返回值,如果有,只是作为指令是否执行成功标志。

以下为各POKE指令在SCL中应用。





脉冲指令用于将输入脉冲化,在某种情况下,如果未能将输入脉冲化,则每个扫描周期都将执行指令(如自加/自减指令等),会得到错误结果。

其它品牌PLC脉冲指令无前周期状态位,虽则简化了编程,但是在某些特殊情况下会导致错误运算结果,以下为实际编程中出现的情况。

之前刚做了一个项目,用的是日系某品牌,该项目在主程序中3次调用某子程序,子程序中有下降沿脉冲指令用于计数,在调试时发现计数不是按预计出现下降沿脉冲时计数一次,而是不停计数。

反复检查子程序逻辑,未发现问题。*后将子程序只调用一次则计数正常。

经再三思考,发现问题出在子程序中调用了脉冲指令,解释如下:

假设:子程序中使用了形参M0的下降沿脉冲指令,此指令对寄存器D0加计数。**次调用实参为X0,**次调用时实参为X1。

程序运行后X0接通,X1断开。程序执行如下:

步1:X0接通;

步2:**次调用,进入子程序,M0接通;

步3:**次调用结束,M0保持ON;

步4:**次调用,此时因X1未接通,进入子程序时M0为OFF;

步5:M0状态由ON变为OFF,出现下降沿脉冲,D20加1计数;

步6:程序重复执行,则重复以上1~5步。

发生以上情况的原因是当退出子程序时,系统只能保持一次位变量前一周期扫描状态,当**次调用子程序 时,此状态会被错误引用(只调用一次则没问题),  后来将子程序中脉冲指令移到子程序外,测试未发现问题。

查阅了其它PLC资料,发现另一日系品牌及S7-200存在相同问题。但S7-300/400/1200中则可设置可分别设置前一扫描周期状态保持位,不会发生以上问题,以下使用S7-1200及Step7 V11编程时为例。


1) 单次调用脉冲化指令

单次调用脉冲化指令时,只需给其指定一个前周期状态保持位即可,在OB或FC中单次调用脉冲化指令情况较多,分别以LAD及SCL编程时说明:





说明:1.1 在LAD编程中,上一扫描周期状态保持位为M1.0,它保留上一扫描周期的I0.0状态,并与此扫描周期I0.0状态对比,若有上升沿则输出;

1.2 在SCL编程中,利用可保持的位来实现上升沿检测,其中boolTag1为FC或OB输入参数,Tag_39为M1.0的变量名,利用以上语句可实现boolTag1上升沿检测。注意前一扫描周期状态保持位不能为FC的临时参数,因为临时参数在执行扫描时会设置为0,从而导致程序执行达不到要求。


2)多次调用脉冲指令

如果某一FB或FC被多次调用,使用以上方法编程则会出现程序执行达不到要求,分析如上所示,此时可采用方法让每次调用都使用不同的保持位,则可解决以上问题。

如果是在FB中调用脉冲化指令,则比较简单。可利用FB被其它程序块调用的“多重背景”功能,将脉冲化指令的上一扫描周期保持位设置为FB的静态变量则可解决。





程序中boolTag1为FB输入参数,BitMem1为FB静态变量,其在FB多次调用时,会将当前值保存在不同的背景数据块中,从而实现多次调用不互相干扰。

如果是在FC中调用,因为FC并无静态变量,所以可选择用一个输入输出参数来作为前一扫描周期状态保持位,每次调用时先读取状态位,然后保存在输入输出参数中,即可实现多次调用互不干扰。



程序中boolTag1为FC输入参数,boolMem1为FC输入输出参数,因为需先读后写,所以需使用输入输出类型参数。


S7-1200中对位的操作方式比较灵活,既有通常对直接位变量的各种操作,也有对字节,字及双字的位进行操作,以下对各种情况进行说明。

1)位变量的**地址引用

对位于I,Q,M区的**地址位变量是直接引用其的**地址,如I0.1,Q3.5,M10.3等;对位于DB区的**地址,需先在DB中声明,再引用**地址,如DB1.DBX2.0,如未声明即引用,会发生编译警告。




上例中**地址DB1.DBX40.1未在数据块DB1中声明,故在引用时出错;

引用**地址时,依照好的编程习惯,要先在PLC或数据块变量表中对**地址先赋予变量名。

总的来说,引用**有如下几种情况:

1.1 I区:引用格式为I0.1

1.2 Q区:引用格式为Q0.1

1.3 M区:引用格式为M10.0

1.4 DB区,分为:

1.4.1 在DB中定义的位变量,引用格式形如DB1.DBX40.0

1.4.2 在DB中定义元素为Bool型的数组arrayBool[0..n],引用格式形如DB1.DBX0.1,其符号寻址为”标准数据块名”.arrayBool1[n]

1.4.3 FB的背景数据块同样适用于以上2条调用情况。

2)符号寻址

符号寻址有几种情况,*普通的是使用对应**地址的变量名,此变量名在PLC变量表或数据块(含全局数据块及背景数据块);

其二是在程序块中定义字节,字或双字变量,然后以“变量名.Xn”类似形式引用其位变量,注意变量名可以是PLC变量名,DB变量名或FB/FB的接口区变量;

其三是在FB/FC接口区声明变量时对变量进行覆盖,以数组形式进行覆盖,然后在程序中直接引用数组元素即可进行位变量引用,此方法还可进行间接寻址(即数组下标可为变量)。

以上**种情况比较容易理解,在此不以例子来说明,以下重点针对**种及第三种情况进行举例说明。


2.1 符号变量的部分调用

符号变量的部分调用称为”slice”调用,是指定义了一个变量(如长度为双字),则可以对其以部分引用,如以位,字节或字对其引用。

以下以定义一个字变量,然后对其以位引用,分以下几种存储区域说明:

2.1.1 I/Q/M存储区:形式为 “intPLCTag1”.xn,其中intPLCTag1为PLC变量名

2.1.2 DB存储区:形式为 “标准数据块”.int1.xn,其中int1为DB“标准数据块”中变量名

2.1.3 FB/FC接口区:形式为 #intTag1.xn,其中intTag1为接口区变量

说明:接口区变量以前辍#标注,PLC变量或DB变量以双引号标注。

但是,使用V11编程及V2.2硬件时,在SCL编程时,只能对接口区参数进行slice引用。使用V12则不会出现此问题。





2.2变量覆盖位引用

只有以标准模式(与S7-300/400兼容)形式调用DB的FB或FC(或FB中保持性为“在IDB中设置”的变量)才能创建变量覆盖,当以位元素数组覆盖变量时,即可对该变量进行位引用。



上例中intTemp1为FB的临时变量,用于传送数组下标。intTag1为FB的输入变量,atintTag1[0..15]为其覆盖变量,其元素为Bool型,对其数组元素的引用即可体现位变量调用。

上例作用相当于部分引用形式的 #intTag1.Xn,但不同之处是可以通过变更数组下标来实现间接寻址,而变量名的部分引用则不能变更。


高手:

同样的程序,用FB,和FC,结果有微小区别
 如图


江湖小虾:

S7-1200使用定时器时,必须先指定一个定时器数据结构,否则无法使用,定时器的数据结构创建有3种方法:在全局数据块中创建,在单重背景数据块中创建,在多重背景数据块中创建。其中全局数据块中创建的定时器结构只适用于LAD指令,多重背景数据块中创建的定时器结构只适用于FB编程中。
 1) 定时器数据结构创建
 1.1 全局数据块中创建
 


 说明:可在标准或优化调用的全局数据块中创建定时器数据结构,但是在优化的数据块中创建数据结构时可分别对每一变量设定“保持”特性。
 1.2 创建FC或FB时在单重背景数据块中创建

说明:在FC中调用IEC定时器(只能是创建单重背景数据块)或在FB中以单重背景创建定时器数据结构时出现以上画面,其会创建一个背景数据块,数据块中只包含一个定时器数据结构。
               如上图,在FC中调用定时器时,会创建一个单重背景数据块IEC_Timer_0_DB(数据块命名可自行更改),此数据块只包含一个定时器数据结构,如图30所示。
               注意与全局数据块中创建的定时器数据结构对比,其无变量名及数据类型。

 1.3 多重背景数据块中创建定时器数据结构

说明:在FB中调用定时器时,可选择以多重背景创建数据块,此时数据块与FB共享其背景数据块,并且定时器数据结构就创建在静态变量区,从图32可看出,有定时器变量名及数据类型,如同在全局数据块中创建一样,定时器变量数据类型为“IEC_TIMER”。
 如果是在SCL编程语言时,调用定时器如上所选多重背景数据块,则在FB静态变量区的定时器数据结构类型与LAD下有所不同,其类型为“TON_TIME”或“TOF_TIME”,“TP_TIME”,“TONR_TIME”,依调用时所选定时器不同而不同。

2)在程序中对定时器进行编程
              创建了定时器数据结构,如何在程序中进行使用?依据编程语言及所选用的定时器数据类型不同而不同,以下分几种情况进行说明:
           2.1 LAD中调用
              LAD中调用定时器时,若是调用的是IEC定时器,会首先要求创建背景数据块(因IEC定时器属于SFB),创建相应的单重或多重背景数据块后,自动在指令上填写所创建的数据结构(若为单重,则为背景数据块名,若为多重,则为静态变量区变量名),如图34所示。

此定时器背景数据块可更改为在全局数据块中预先定义的数据结构名,编译可通过,如下图36所示。
       此种定时器调用时需指定定时器名,启动位,预定义时间及当前值存储器。
              在LAD中还可以调用另一种类型定时器,即线圈型定时器,此定时器调用时与前述定时器不同,只需指定定时器名(即数据块名),启动位及设定时间,如下图所示:

以上调用线圈型定时器时数据块也可不用全局DB中预先定义的定时器数据结构,选用单重背景数据块(FB或FC中)或多重背景数据块(FB中)也可以,编译可通过,但不知执行时是否有问题。
 
          2.2 SCL中调用
             在SCL中调用定时器指令时,会自动将创建的单重背景数据块名称或多重背景数据块的静态变量名插入到调用的指令中,并且不能更改。
             与在LAD中调用不同,其需设定参数包含输出位,随后程序中可直接引用。

注意以上区别:单重背景数据块时其定时器类型为IEC_TIMER,故调用时区分定时器种类(以TON等进行区分,但可手动更改如TOF),而多重背景调用时在变量类型中已指定为TON_TIME,故后直接跟参数,但如果在参数接口表中手动更改为TOF_TIME(无选择,只能手动输入)。
            这也是为什么不能变更定时器数据块的原因(但是可以在相同数据块定义方式中变更,如图37中数据块名称可变更为“IEC_Timer_0-DB”,因为同属单重背景数据块。
            注意:参数“ET”用于存储当前时间,按Step7 V11语法,IEC时间存储器为32位,故只能用DWord数据类型,若为其它数据类型会报错。


酱油甲:

楼主科普得不错,求精!
 我给你献花了……

酱油乙:

感谢楼主  刚接触STEP7V12  学习了


   江湖小虾:

V11起直接支持字节位寻址。比如定义一个状态字STW 为一个word.你梯形图中直接可以这样访问,STW.0,STW.1,STW.2...STW15,不需要覆盖
           
 如果引用固定的位地址,用变量名slice引用没问题;
 如果需要变址寻址(如STW.n,改变n的值时引用不同的位),则需要覆盖,并通过变更数组下标来引用不同的位。

在SCL编程模式下,如果要在FC中调用IEC定时器,需为其创建一个背景数据块,如果FC中使用的定时器较多,则可能因背景数据块较多造成数据凌散,*好的解决方法是使用FB,将定时器数据结构定义在静态变量区则可。如果不想使用FB,同时不考虑到程序的移植(程序中包含有全局变量,不利于程序移植),则利用DIY定时器也可解决此问题,方法如下:
     1、设置系统时钟存储器字节并激活,方法是:在项目树 PLC名称项上右键单击->选择“属性”以打开PLC系统属性设置对话框->选择“常规”选项卡->选择“脉冲发生器(PTO/PWM)”下的“系统和时钟存储器"->设置并激活系统时钟存储器位,如下图所示,M0.0即为10Hz脉冲,其符号为”Clock_10Hz";

 2、对时钟脉冲取上升沿,为以后在程序中计数作准备。下例中是将所有时钟脉冲取上升沿程序在FC中定义,方便程序的移植,如下图所示,10Hz脉冲上升沿为M2.0,符号为“PosEdge_10Hz”,是在系统变量表中定义;

 3、如果在程序中需要用不用到定时器的,则对以上时钟脉冲上升沿信号进行计数,对计数值进行比较判断并输出,即可依据不同的计数值得到不同的定时时间,简单的例子如下:




酱油丙:

收藏了,从楼主对脉冲指令的分析与比较就可以看出楼主功力深厚了.





你可能感兴趣: 工控菜鸟园 图片 自动化系统 SIMATIC S7-1200 操作系统 PLC 西门子
无觅相关文章插件,快速提升流量