如何在西门子PLC中清除一整个数据块
1500系列版本
FUNCTION "F_ClearDB" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 1.0
VAR_INPUT
IN0 : DB_ANY;
END_VAR
VAR_TEMP
TEMP1 : Int;
END_VAR
BEGIN
NETWORK
TITLE =
LAR1 P#DBX0.0;
OPN #IN0;
L DBLG;
L 2;
/I;
M001: T #TEMP1;
L 0;
T W[ AR1, P#0.0];
+AR1 P#2.0;
L #TEMP1;
LOOP M001;
END_FUNCTION
因为1500系列支持STL语言,而STL语言中有一个很好用的指令 L DBLG,这个指令将会返回DB块的长度(in Bytes) in Runtime.知道DB块的长度就可以清除这个数据块的数据了.
1200版本
FUNCTION "F_ClearDB" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
"DB" : DB_ANY;
END_VAR
VAR_TEMP
db_index : UInt;
i : UInt;
Size : UInt; // default db size=0
db_byte : Byte;
max_index : UInt;
err_id : Word;
zero : Byte;
END_VAR
BEGIN
//-------------------------------------------------------------------
#db_index := 0; // initialize
#zero := 0;
#max_index := 2000; // set a constraint to prevent watchdog timeouts
//===================================================================
// not strictly required to handle errors internally
// but if a FW or service pack or update suddenly causes errors,
// this should prevent cpu crashes
// ==================================================================
//
// clear out any existing error conditions
#err_id := GET_ERR_ID();
// emulates TRY ... CATCH ... found in other computer languages
REPEAT
ENO := TRUE; // required to make it work
// try to look at byte @ db_index
#db_byte := PEEK_BYTE(area := 16#84, dbNumber := #DB, byteOffset := #db_index);
#db_index += 1;
UNTIL (#db_index >= #max_index) OR (NOT ENO) END_REPEAT;
IF NOT ENO THEN
#Size := #db_index - 1; // copy count when ENO went off (before inc(1) )
ELSE
#Size := 0; // DB does not exist or is very large
END_IF;
REPEAT
POKE(area := 16#84,
dbNumber := #DB,
byteOffset := #i,
value := #zero);
#i += 1;
UNTIL (#i >= #Size) END_REPEAT;
// FOR #i := 0 TO #Size BY 1 DO
// ;
// END_FOR;
END_FUNCTION
1200系列不支持STL语言,那么获取DB块长度就要使用一点技巧了,这里使用的是ENO
REPEAT
ENO := TRUE; // required to make it work
// try to look at byte @ db_index
#db_byte := PEEK_BYTE(area := 16#84, dbNumber := #DB, byteOffset := #db_index);
#db_index += 1;
UNTIL (#db_index >= #max_index) OR (NOT ENO) END_REPEAT;
以上这一段代码就利用了ENO的特性,当PEEK_BYTE指令报错时,说明当前#db_index已经超过了数据块的最大长度,同时将ENO置为0;
这样我们就获取了该数据块的长度

Comments | NOTHING