如何在西门子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;

这样我们就获取了该数据块的长度


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。