| 作者 | 主题 |
|---|---|
|
谦 总坛主
经验值:23725 发帖数:3679 精华帖:8 |
楼主
主题:应用探讨——PLC 数据类型探讨
各位同学是否有以下疑惑:
1. INT数据类型与WORD 数据类型有何区别?DINT与TIME呢? 2. S5 TIME数据类型结构是什么样的?怎样自行修改或生成符合S5 TIME数据类型的值? 3. 仪表传送一组流量数值,是用字符串方式发送,接收到数值后,怎样还原为浮点数? 4. MOVE指令与数据类型转换指令怎样区分?都有什么样的应用场合? 5. 隐式转换和显示转换是什么含义,在TIA 博途中,设置IEC检查对数据类型转换会有什么影响。 另外,复杂数据类型的应用,如:STRUCT与UDT的应用与区别、*数组、ANY数据类型,各种数据类型的存储与寻址方式,相互转换也在本话题讨论范围之内,大家不要吝啬笔墨,踊跃发言,谈谈应用过程中的疑惑与认识,希望大家收获多多! 活动奖励: 此次集中交流将持续至11月12日,其中所有精华帖作者将获得加倍精华奖励积分;最终所有有效留帖的网友将获得加倍发帖积分。更多积分带给您更多奖品兑换的自由。 对于有突出发言贡献的网友可获得金币奖励,可以在当前的兑换奖品中兑换奖品。 交流结束后也将专门整理重要内容,供广大网友分享参考。 预祝大家交流愉快,收获丰富! |
|
Automann 至圣 经验值:18299 发帖数:6168 精华帖:137 |
5楼
主题:回复:应用探讨——PLC 数据类型探讨
字符串转换为浮点数的方法
可以用程序编辑器的IEC库中的FC39 STRNG_R,将字符串转换为REAL数据类型格式变量。 用IEC库中的FC30 R_STRNG,可以将REAL格式的变量转换为字符串。 字符串由符号、小数点前的1位数字、小数点、小数点后的7位数字、E和2位指数数字字符组成。 下面是一个例程: 在DB1中定义字符串STR1[14],下面是OB1中的程序: CALL "R_STRNG" //调用FC30,将REAL格式变量转换为字符串 IN :=1.234567e+003 RET_VAL:=DB1.STR1 CALL "STRNG_R" //调用FC39,将将字符串转换为REAL格式变量 S :=DB1.STR1 RET_VAL:=MD0 由监控可知FC30将1.234567e+003转换后,DB1.STR1中的字符串为’+0.1234567E+04’。用FC39将字符串DB1.STR1转换后,MD0中的浮点数为1.234567e+003。
追求完美
|
|
剑忠 奇侠 经验值:9641 发帖数:622 精华帖:57 |
8楼
主题:回复:应用探讨——PLC 数据类型探讨
一、在S7编程中字符类型[CHAR]使用比较少见,但在一些与条码扫描的通讯设备中却较为常见,例如工装线产品质检和计数或商场收银系统。
二、这类条码扫描设备通常先与PLC进行RS232C或RS485串口通讯后读入CHAR数据类型,然后经组合和转换后,在触摸屏Touch中显示。 三、其实CHAR数据类型处理很简单,具体使用事项和方法如下: 1、首先CHAR字符采用ASCII编码; 2、其次CHAR字符占用一个Byte; 3、因此将读取的CHAR字符存放至定义为CHAR类型的存储区变量中,例如MB2→CHAR即可; 4、如果要对定义的CHAR类型的变量赋值,需对输入的字符常量加一对单引号,例如:'$'、'F'、'【'、'?'。 5、使用效果见以下ASCII码表与程序对照图。
大学之道,在明明德,在亲民,在止于至善。
|
|
只求进步 游侠 经验值:547 发帖数:125 精华帖:2 |
13楼
主题:回复:应用探讨——PLC 数据类型探讨
2. S5 TIME数据类型结构是什么样的?怎样自行修改或生成符合S5 TIME数据类型的值?
1) S5TIME为16位数据,BCD码格式。当使用S5TIME时,最大计时为S5T#2h46m30s(9990s). 格式如:2#0011 1001 1001 1001,即S5T#2h46m30s 10s 9 9 9 第14,13位表示时间基准,00为10ms,01为100ms,10为1s,11为10s.上例为11,即10s时基。 后12位为BCD码表示的时间值,上例为999,则999*10s=2h46m30s. 2)知道S5TIME的格式后,就可以在程序中正确的使用了。常见的如在触摸屏中有个INT变量设定的时间, 在程序中要转换成S5TIME.(INT转S5TIME). 因为S5TIME为BCD码格式,所以要先将INT转BCD(ITB).记得一定要转。可以看3楼的例子。我们也可以 自己编程做一下实验。ITB不写的话就会报错。 L 999 //0000 0011 1110 0111 ITB //0000 1001 1001 1001 L W#16#3000 //0011 0000 0000 0000 OW T MW 700 //0011 1001 1001 1001 (S5T#2h46m30s) A M 100.0 L MW 700 SD T 1 3)其他关于INT,TIME和S5TIME的转换见下帖。 http://www.ad.siemens.com.cn/club/bbs/post.aspx?b_id=4&a_id=898840
所有一切只不过是宇宙整体的彰显和表达!
|
|
剑忠 奇侠 经验值:9641 发帖数:622 精华帖:57 |
16楼
主题:回复:应用探讨——PLC 数据类型探讨
字符串数据类型[STRING]的使用也比较少见,常用于存储消息文本。
关于STRING类型变量使用事项如下: 1、STRING变量字符串以ASCII编码存储每个字符,最大长度256Byte,前两个Byte存储字符串长度信息,所以STRING变量最多包含254个字符。其中第一个Byte存储最大长度;第二个Byte存储实际字符长度。 2、STRING类型的变量可传递至相同类型(即相同的STRING长度)的块参数中,也可以传递至POINTER或ANY类型的FC/FB块参数中。 3、给STRING变量赋值常量需使用一对单引号,例如:'String'、'S7'、'failure_4'。 4、如果用ASCII编码的字符赋值,则该字符也必需使用一对单引号,而如果包含用于控制术语的特殊字符,则必需在字符前添加前缀符号$。例如:$$→美元字符;$P→换页字符;$L→换行字符;$R→回车字符;$T→空格字符。 5、STRING变量定义声明和初始化方法:变量名称:STRING[最大字符数]: '初始化文本',变量定义声明时可以无初始化文本。例如:FALT_SIG:STRING 'Motor failure_4'、Warning:STRING [50] ''。 如果变量定义声明时未指定最大字符数,那么STL/LAD/FBD程序编辑器则自动默认长度最大为254个字符。 6、可使用基本的STL指令访问STRING变量的各个字符。例如:L FALT_SIG[5] //装载变量FALT_SIG的第5个字符,即'r'。 7、还可以使用IEC库的FC功能块实现对STRING变量的访问和处理。
大学之道,在明明德,在亲民,在止于至善。
|
|
Automann 至圣 经验值:18299 发帖数:6168 精华帖:137 |
17楼
主题:回复:应用探讨——PLC 数据类型探讨
数据类型是什么?
数据类型是什么?数据类型是人为规定的数据的属性。在计算机和PLC中,数据实际上以二进制数的形式储存。按长度分为1位、8位、16位、32位的二进制数据。 除了数据的长度,数据类型包含了更多的内容,例如32位的数据类型有双字、32位整数、Time、浮点数、TIME_OF_DAY等。 数据的数据类型需要在符号表、块的局部变量表中定义,因此数据类型是人为指定的数据的属性。 指令和块的输入、输出参数的实参的数据类型必须与对应的形参要求的相同,否则程序将会出错。 OB40的参数OB40_MDL_ADDR的数据类型为WORD,不能直接用于要求数据类型为INT的整数比较指令。怎样解决这一难题呢?在梯形图中,可以用MOVE指令把OB40_MDL_ADDR的值传送给没有定义数据类型的一个绝对地址,例如MW10,MW10就可以用于比较指令了。MW10并没有因此自动获得数据类型INT,只是CPU“认为”MW10中的数据类型是INT,CPU被我们蒙骗了! 我见过不良小贩把白色的小鸡染成五颜六色来骗小孩,放到水里一洗,小鸡的彩色就消失了。如果把小鸡看成数据,染的颜色就是数据类型。把定义了数据类型的数据装入绝对地址MW10或累加器(累加器也是一个特殊的绝对地址),数据类型的属性就被剥去了,只剩下赤裸裸的数据,就像小鸡的颜色被水洗掉了一样。这时就可以把数据当作规定了长度的各种数据类型来使用。
追求完美
|
|
氢气 游侠 经验值:441 发帖数:47 精华帖:8 |
27楼
主题:回复:应用探讨——PLC 数据类型探讨quote:以下是引用YHKingKong在2013-10-15 13:04:12的发言: 利用MOVE指令,可以自动转换类型。 MOVE DBXX.DBD可以直接复制给MD。 主要是数据处理时,需要数据转换。 LAD中的“MOVE”指令,类似于STL中的装载指令“L”和传送指令"T",是将原数据原封不动的传送给目的地址。举个例子,DB1.DBD0为REAL数据类型(值为1.111),DB1.DBD4是DINT数据类型,使用"MOVE"指令将DB1.DBD0传送至DB1.DBD4中,得到的结果是什么呢?会是“L#1”吗?如果使用指令"ROUND"呢? 结果是使用"MOVE"指令,在DB1.DBD4中得到的结果是数据1.111按照IEE754标准存储的32个Bit组成的DINT值,即L#1066284351,使用ROUNT指令得到的是L#1。所以MOVE指令应理解为按位传送,而非数据类型转换指令。 17楼的小鸡穿衣比喻很形象,一组二进制数究竟是什么,不仅取决于小鸡本身,还取决于它的颜色。
---------------------来自西门子工程师
|
|
氢气 游侠 经验值:441 发帖数:47 精华帖:8 |
35楼
主题:回复:应用探讨——PLC 数据类型探讨quote:以下是引用Automann在2013-10-21 18:05:16的发言: quote:以下是引用氢气在2013-10-21 17:09:53的发言: quote:以下是引用Automann在2013-10-18 07:25:41的发言: 对ANY数据类型的错误理解的分析 最近看到有个下面的帖子(ANY指针可以这么用么?): 各位好,最近学习一下ANY指针,写了段测试代码,但是无法执行,请问是不是ANY指针不能这么使用呢?谢谢! 代码如下: L P##TEMP0 LAR1 L W#16#1001 T W [AR1,P#0.0] L W#16#0 T W [AR1,P#2.0] L W#16#0 T W [AR1,P#4.0] L DW#16#81000000 T D [AR1,P#6.0] SET A [AR1,P#0.0] = Q 0.0 下面是我的分析: 楼主上面这段代码实际上是在填写ANY的10个字节的值,虽然辛苦,做的却是无用功。问题在于他没有理解ANY的使用方法。 ANY是参数类型,只是用来作块的输入、输出参数。在调用逻辑块时, ANY用于将任意的数据类型传递给声明的形参。ANY的实参可以是单个的任意地址,也可以是一片连续的地址区,例如P#DB1.DBX0.0 INT 50(DB1中从DW0开始的50个整数)。但是ANY的10个字节的值是操作系统根据块的实参的值自动生成的,而不是用户生成的。我们可以用寄存器间接寻址读取ANY的10个字节中包含的大量信息,例如实参的基本数据类型,数据块的编号,重复因子(变量的个数),地址区的起始地址等等。 其实ANY指针的值完全可以由用户自行生成,作为实参传给功能块的输入参数,这样就能实现“变址寻址”。例如使用SFC20将不同DB块的值传递给DB100: L P##TempAny LAR1 L W#16#1001 //数据类型BYTE T W [AR1,P#0.0] L W#16#10 //重复因子 T W [AR1,P#2.0] L MW 10 //确定DB块 T W [AR1,P#4.0] L DW#16#84000000 //DB存储区 T D [AR1,P#6.0] CALL "BLKMOV" SRCBLK :=#TempAny RET_VAL:=MW12 DSTBLK :=P#DB100.DBX0.0 BYTE 10 这样,就实现了将某个DB块中前10个字节传送到DB100中,究竟是哪个DB,完全由MW10决定。关于间接寻址的相关内容,参考论坛其它帖子,或者下载中心文档F0595,这里不做过多讨论。 调用SFC 20,一般我们直接使用SRCBLK的指针格式的实参,DBx是数据块的地址: CALL "BLKMOV" SRCBLK :=P#DBx.DBX0.0 BYTE 10 RET_VAL:=MW12 DSTBLK :=P#DB100.DBX0.0 BYTE 10 氢气侠写的一大堆代码也可以实现同样的功能,但是工作量太大,也容易出错,比如说 数据类型BYTE 好像应该是W#16#1002,而不是16#1001。 氢气侠的用法当然也有好处,程序不容易读懂,有一定程度的保密性。 谢谢指正!确实是W#16#1002。 我举这个例子目的是告诉大家ANY的用法,不止局限于以类似“P#DB1.DBX0.0 BYTE 10”这样的格式去使用它。而是要根据ANY数据类型的结构去打造自己的“ANY数据”,此数据在作为参数传递的同时,还可以用于间接寻址。例如上例中,数据源地址不是固定的,究竟是哪个DB块,由MW10决定,而MW10可以是HMI传递过来的数据。比如程序中有90个配方,分别存储与DB1~DB90中,究竟将哪个配方传送至DB100中使用,由MW10(HMI)决定。所以程序这样书写跟保密性无关。 另外ANY的魅力不仅在于“重构”,还在于将其“解析”(通常都是这种用法),“解析”后可以得到其中的地址、长度、数据类型等信息。参考间接寻址的官方连接: http://support.automation.siemens.com/CN/view/zh/24519683 其中的问题:如何计算ANY 型指针的偏移量或改变指针? 如何设置带有"ANY"或"POINTER"数据类型的功能块? 说明了如何将ANY数据类型“重构”与“解析”。更多间接寻址或ANY数据类型应用也可参考下载中心F0670和F0595或者相关书籍。 关于间接寻址的内容,请大家移步至坛子:主题:应用探讨——西门子指针编程使用探讨 http://www.ad.siemens.com.cn/club/bbs/post.aspx?b_id=4&a_id=936225&s_id=0&num=142#anch 这里就不做深入探讨了,而是更多关注于数据结构方面的内容。
---------------------来自西门子工程师
|
|
Automann 至圣 经验值:18299 发帖数:6168 精华帖:137 |
50楼
主题:回复:应用探讨——PLC 数据类型探讨quote:以下是引用氢气在2013-11-08 09:45:47的发言: 我这有几个问题: 1.数组数据类型,初始值是怎么设定? 2.UDT 与 STRUCT的初始值怎么设定,如果改变UDT中的一个变量,那么程序中所有用到此数据类型的地方是否都改变?程序是否能编译通过?怎么处理方便? 3.在FB或者FC的接口参数定义区内,数据类型设定会有Block_FB,Block_FC,Timer,Counter等,在FB的静态变量里,有FB 另外,很多工程师会发现在S7-1200和S7-1500中出现了更多的数据类型,如长实数(LReal),DTL(长日期和时间),长定时器(LTime),有用过的将经验分享下,呵呵。 给数组元素赋初值:在ARRAY所在的行的“初始值”列中给数组元素赋初值,各元素的初值之间用英语逗号分隔,例如有6个元素的初值可以写成“22,30,5,0,0,0”。若相邻元素的初值相同可以简写,上述初值可以简写为“22,30, 5,3(0)”。 UDT 与 STRUCT的元素要根据元素的数据类型逐个单独赋初始值。 FB、FC的参数类型Block_FB,Block_FC,Timer,Counter只能作输入参数的数据类型,用来设置定时器、计数器、FB、FC的地址。有了这些参数类型,在FB、FC的内部可以不使用定时器、计数器、FB、FC的绝对地址,保证了逻辑块的可移植性。 FB的静态变量里的FB
追求完美
|
|
老学童 奇侠 经验值:8218 发帖数:765 精华帖:32 |
51楼
主题:回复:应用探讨——PLC 数据类型探讨
DATE_AND_TIME类型的理解与实践
DATE_AND_TIME即DT类型是S7复杂类型的一种,由8个字节组成,从字节0到字节7用BCD码分别表示年、月、日、小时、分、秒、毫秒的十分位和百分位值、毫秒的千分位值和周日期(星期几),即: 字节0 -------->年 字节1 -------->月 字节2 -------->日 字节3 -------->小时 字节4 -------->分 字节5 -------->秒 字节6 -------->毫秒的十分位和百分位值 字节7 -------->7~4位为毫秒的千分位值,3~0位为周日期(星期几) 在实际运用中,常常需要将DT类型实参的每个字节进行BCD到INT的类型转换后才能使用,本人通过编辑以下程序增强了对DT类型的理解和运用,本程序完全自行编写并经过仿真验证,在此与大家分享: OB1: NETWORK TITLE = CALL SFC 1 ( //调用标准功能SFC1读取系统日期和时间 RET_VAL := DB6.DBW 26, //SFC1执行错误代码 CDT := DB6.VAR1_DT); //保存至DB6.DBX0.0开始的8个字节 NETWORK TITLE = CALL FC 1 ( //调用FC1进行数据转换 ActualDateTime := DB6.VAR1_DT); FC1: L P##ActualDateTime //读取并加载DB6.DBX0.0开始DT数据指针 LAR1 //将指针地址装入地址寄存器1 L 0 L W [AR1,P#0.0] //将指针中的DB块号加载至累加器1 ==I JC _001 //判断是否为DB数据块,否则跳转至_001 T #DB_NO //保存DB块号 OPN DB [#DB_NO] //打开DB块 _001: L D [AR1,P#2.0] //将指针中的区域指针加载至累加器1 LAR1 //将数据源(DT型)区域指针保存至地址寄存器1 LAR2 //将目标(INT型)区域指针保存至地址寄存器2 L 7 //设置循环次数 _002: T MW 10 //循环次数计数 L B [AR1,P#0.0] //依次加载DT数据前7个字节 BTI //BCD到INT转换 T W [AR2,P#8.0] //保存至DB6.DBX8.0开始的7个INT类型数据区 +AR1 P#1.0 //数据源(DT型)区域指针偏移1个字节 +AR2 P#2.0 //目标(INT型)区域指针偏移2个字节 L MW 10 LOOP _002 //通过LOOP循环依次将DT型的每个字节转换为INT型 L B [AR1,P#0.0] //将DT的第8个字节加载至累加器1 SRW 4 //将累加器1的低字右移4位(滤掉‘周日期’的BCD码) BTI //BCD到INT转换 T W [AR2,P#8.0] //保存至DB6.DBX8.0开始的第8个INT类型数据区 L B [AR1,P#0.0] //将DT的第8个字节加载至累加器1 AW W#16#F //与W#16#F‘字与’(滤掉毫秒千分位BCD码) +AR2 P#2.0 //目标(INT型)区域指针偏移2个字节 T W [AR2,P#8.0] //保存至DB6.DBX8.0开始的第9个INT类型数据区 BE //块结束 DB6: DATA_BLOCK DB 6 TITLE = VERSION : 0.1 STRUCT VAR1_DT : DATE_AND_TIME ; //实际日期时间 YEAR_I : INT ; //INT类型的‘年’值 MONTH_I : INT ; //INT类型的‘月’值 DAY_I : INT ; //INT类型的‘日’值 HOUR_I : INT ; //INT类型的‘时’值 MINUTE_I : INT ; //INT类型的‘分’值 SECOND_I : INT ; //INT类型的‘秒’值 MILLIS_12_I : INT ; //INT类型的‘毫秒’的十分和百分位值 MILLIS_3_I : INT ; //INT类型的‘毫秒’的千分位值 WEEK_D_I : INT ; //INT类型的‘星期几’值 ERROR : INT ; //SFC1执行错误代码 END_STRUCT ; BEGIN VAR1_DT := DT#90-1-1-0:0:0.000; YEAR_I := 0; MONTH_I := 0; DAY_I := 0; HOUR_I := 0; MINUTE_I := 0; SECOND_I := 0; MILLIS_12_I := 0; MILLIS_3_I := 0; WEEK_D_I := 0; ERROR := 0; END_DATA_BLOCK ![]() 参考: http://www.ad.siemens.com.cn/club/bbs/post.aspx?b_id=4&a_id=1071117&s_id=0&num=4#anch http://www.ad.siemens.com.cn/club/bbs/post.aspx?b_id=4&a_id=873506&s_id=0&num=35#anch
人的生命似洪水在奔流,不遇着岛屿、暗礁,难以激起美丽的浪花。
|
|
老学童 奇侠 经验值:8218 发帖数:765 精华帖:32 |
53楼
主题:回复:应用探讨——PLC 数据类型探讨
友情提醒:
本人在51楼的原贴存在一些问题,现已在原贴中更正! 主要的问题在DT类型的第7字节和第8字节的理解和程序处理,本人发现很多以往的帖子对此陈述也不是非常清晰: .xyz(秒) x..........毫秒十分位值 y..........毫秒百分位值 z..........毫秒千分位值 DT类型的第7字节的BCD码是毫秒的十分位和百分位值 DT类型的第8字节的BCD码7~4位是毫秒千分位值,3~0位是星期几。
人的生命似洪水在奔流,不遇着岛屿、暗礁,难以激起美丽的浪花。
|
|
老学童 奇侠 经验值:8218 发帖数:765 精华帖:32 |
54楼
主题:回复:应用探讨——PLC 数据类型探讨
“DINT和TIME呢?”,我觉得坛主问到的问题一定有其深义,本人就此个问题经过以下思考:
咋一看这两种类型似乎很简单,手册上写的很清楚: DINT是32位有符号双整数类型,值域:L#-2147483648~L#2147483647 TIME是IEC时间类型,值域:T#-24D_20H_31M_23S_648MS~T#24D_20H_31M_23S_647MS 仔细琢磨觉得真的很有意思,TIME类型在赋值时是按"T#xxDxxHxx...."格式赋值的,而在S7内部其实是:以1毫秒为基本时间单位的32位有符号双整数表示时间值,因此,将TIME的实参赋值给一个TIME的形参后或保存到一个DINT类型的存储单元时,就变成了DINT值,本人用以下程序进行了仿真: OB1 CALL FC 1 T:=DB1.DBD0 D:=DB1.DBD4 FC1: L #T //TIME类型 T #D //DINT类型 DB1: DATA_BLOCK DB 1 TITLE = VERSION : 0.1 STRUCT T : TIME := T#1D1H; D : DINT ; END_STRUCT ; BEGIN T := T#1D1H; D := L#0; END_DATA_BLOCK ![]() ![]() 从以上仿真图片可以看出: 1. TIME类型在S7内部本质上就是一个DINT类型,就像廖老师说的不过是“染成五颜六色的小鸡”; 2. 当将TIME型变量赋值给DINT型变量(见上述程序)应该是隐式转换的一种。 从中也可以体会出IEC TIME的以下优点: 1. 具有唯一的基本时间(1毫秒); 2. TIME实参在赋值给形参后,无需转换就可以直接用其它32位类型一样计算方法进行计算,例如:+D, -D, *D, /D等等; 3.转换其它时间类型非常方便,例如: L #T //TIME类型 L L#86400000 //一天(24小时)的毫秒值24*3600*1000 /D T .... //得到的就是‘天’数 求模后的值可以继续计算小时、分、秒等等,实现IEC TIME到其它类型,例如DT类型等,的转换。
人的生命似洪水在奔流,不遇着岛屿、暗礁,难以激起美丽的浪花。
|