扩展 S7-200 表指令
日期:2008-2-26 11:47:00 来源: 作者:ttzdh 点击:
点击【 大 中 小 】放大字体.
不务正业太久,该言归正传了。
西门子 S7-200 的只有 4 条与表相关的指令:
ATT :添加数据
FIFO :先进先出
LIFO :后进先出
FIND :查找表
只能从表头删除数据,从表尾添加或删除数据,虽然可以方便的实现队列和栈的结构,但没有在表中间存取数据的指令,使得数据的随机访问和存储很不方便。
这个问题早在几天前在中华工控网工论坛中就有人提出了,因为当时有事,心思也不在那,所以只是简单的给出了一种解决的思路。今天下午得空做了个试验,成功的为 S7-200 增加了4条指令,使 S7-200 具有完整的线性表处理能力。增加的 4 条指令如下:
指令图解:
指令说明:
① GetAt --- 按索引号从表中间取数
pTBL 表头地址(双字)
wIndex 索引号(字)
fError 错误标志(位)
wValue 返回数据(整型)
错误条件:索引号超出范围,fError 置位
② RemoveAt --- 按索引号从表中间取数并删除该数据
与 GetAt 相同,只是取出数据的同时删除该数
③ InsertAt--- 按索引号将数据插入表中间
pTBL 表头地址(双字)
wIndex 索引号(字)
wData 待插入数据(整型)
fError 错误标志(位)
错误条件:空表、满表、索引号超出范围,fError 置位
④ SortTBL--- 对表中已有数据排序
pTBL 表头地址(双字)
fMode 排序方式(位),true 为升序,false 为降序
应用举例:
为了兼容 S7-200 的标准表指令,这 4 条指令采用与 S7-200 完全相同的表结构,索引号的范围也与标准指令相同:0~(EC-1)。假如已经用标准指令创建了表,表头在 VW200,则可按如下方式使用:
从位置 2 取数据,结果放在 VW0,错误标志 M0.0
CALL GetAt &VW200, 2, M0.0, VW0 //注意不要掉了 VW200 前面的取地址符号 &
删除位置 5 的数据,返回数据放在 VW0,错误标志 M0.0
CALL RemoveAt &VW200, 5, M0.0, VW0
在位置 3 插入数据 99,错误标志 M0.0
CALL InsertAt &VW200, 3, 99, M0.0
从小到大排序表
CALL SortTBL &VW200, SM0.0
指令代码:
为了方便习惯于梯形图编程的朋友分析代码,下面的代码以兼容梯形图方式编写。
以下代码是从 MicroWIN V4.0SP1 中导出来的完整格式,可以将它们用文本编辑器保存为 AWL 文件,在 MicroWIN 中选择“文件”-“导入...”菜单,打开刚保存的 AWL 文件直接按原格式导入,这样可以保留子程序中的符号名,具体代码说明请参考注释。
因为采用了与标准相同的结构,可以将它们制作成库,在任意项目中使用。但为了兼容梯形图方式,代码不是很简练,在转换成库之前,可以将它们换成纯 STL 语句,提高代码执行效率。
① GetAt
SUBROUTINE_BLOCK GetAt:SBR0
TITLE=按索引值从表中取数
//
// 返回删除的数据,索引范围:0~EC-1,索引超出范围时错误标志置位
//
VAR_INPUT
pTBL:DWORD;// 表头地址
wIndex:WORD;// 索引号(从0开始)
END_VAR
VAR_OUTPUT
fError:BOOL;// 错误标志
wValue:INT;// 输出数据
END_VAR
VAR
dOffset:DWORD;// 检索指针
END_VAR
BEGIN
Network 1 // 范围检查
// 索引值超出范围,置错误标志
LD SM0.0
CALL SBR4, LD0, LW4, L6.0
A L6.0
CRET
Network 2 // 获取数据
// 表内偏移量:索引 × 2 + 4
// 数据地址: 表内偏移 + 表头地址
LD SM0.0
SLW LW4, 1
+I 4, LW4
ITD LW4, LD9
+D LD0, LD9
MOVW *LD9, LW7
END_SUBROUTINE_BLOCK
② RemoveAt
SUBROUTINE_BLOCK RemoveAt:SBR1
TITLE=从表中间删除数据项
//
// 返回删除的数据,索引范围:0~EC-1,索引超出范围时错误标志置位
//
VAR_INPUT
pTBL:DWORD;// 表头地址
wIndex:WORD;// 索引号(从0开始)
END_VAR
VAR_OUTPUT
fError:BOOL;// 错误标志
wValue:INT;// 输出数据
END_VAR
VAR
dOffset:DWORD;// 检索指针
dOff2:DWORD;// 检索指针2
wMoveCnt:WORD;// 需要移动的项数目
wLoop:WORD;// 循环计数
END_VAR
BEGIN
Network 1 // 取得数据
LD SM0.0
CALL SBR0, LD0, LW4, L6.0, LW7
A L6.0
CRET
Network 2 // 表长减1,并计算需要移动的项数
LD SM0.0
MOVD LD0, LD9
+D +2, LD9 // 指向表长 EC
DECW *LD9 // 表长减 1
MOVW *LD9, LW17
-I LW4, LW17 // 需要移动的项数
Network 3 // 删除的项在表尾
// 不需要移动,直接返回
LDW= LW17, 0
CRET
Network 4 // dOffset 指向第 wIndex 个项,dOff2 指向随后的项
LD SM0.0
INCW LW4
SLW LW4, 1
ITD LW4, AC0
+D AC0, LD9
MOVD LD9, LD13
+D +2, LD13
Network 5 // 后面的 wMoveCnt 个项分别前移一个位置
LD SM0.0
FOR LW19, 1, LW17
Network 6
LD SM0.0
MOVW *LD13, *LD9 // 移动数据
MOVD LD13, LD9 // 指针后移
+D 2, LD13
Network 7
NEXT
END_SUBROUTINE_BLOCK
③ InsertAt
SUBROUTINE_BLOCK InsertAt:SBR2
TITLE=往表中间插入数据项
//
// 正常索引范围:0~EC-1
// 错误:表为空或表已满或索引超出范围,(表为空时直接用标准指令 ATT)
//
VAR_INPUT
pTBL:DWORD;// 表头地址
wIndex:WORD;// 索引号(从0开始)
wData:INT;// 待插入的数据
END_VAR
VAR_OUTPUT
fError:BOOL;// 错误标志
END_VAR
VAR
dOffset:DWORD;// 检索指针
dOff2:DWORD;// 检索指针2
wMoveCnt:WORD;// 需要移动的项数目
wLoop:WORD;// 循环计数
END_VAR
BEGIN
Network 1 // 满表检查
LD SM0.0
MOVD LD0, LD9
+D +2, LD9
AW= *LD0, *LD9
= L8.0
CRET
Network 2 // 索引范围检查
// 索引值超出范围,置错误标志
LD SM0.0
CALL SBR4, LD0, LW4, L8.0
A L8.0
CRET
载入中...
P
L
C
技
术
网
|
可
编
程
控
制
器
技
术
门
户
|
十
万
P
L
C
工
程
师
的
共
同
选
择
!
·最新招聘信息
·最新求职信息
·推荐产品
·推荐厂商
·栏目热门排行
·站内热门排行