ANY pointer copy single bit

JOLTRON

Lifetime Supporting Member
Join Date
Aug 2006
Location
MI
Posts
692
This is a carrie over from another thread I have going.
Just figured I might get more hits with it being labled as ANY pointer.

Other thread:
http://www.plctalk.net/qanda/showthread.php?t=51999

I'm basicly trying to copy the status of a single bit to another.
This is for monitoring and trending.

Current error is 8128 = Alignment error when reading parameter.

My original try had a REP factor of 1, but then i read that the length of an ANY pointer for BOOLS must be divisible by 8.

Code:
FUNCTION "TrendView" : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  MemType : INT ;    
  ByteAddress : INT ;    
  BitAddress : BYTE ;    
  Dest_Any : ANY ;    
END_VAR
VAR_TEMP
  Source_ANY : ANY ;    
  tmpDest_Any : ANY ;    
  tempRetVal : INT ;    
END_VAR
BEGIN
NETWORK
TITLE =

      A(    ; 
      L     #MemType; 
      L     3; 
      >I    ; 
      )     ; 
      A(    ; 
      L     #MemType; 
      L     1; 
      <I    ; 
      )     ; 
      O     ; 
      A(    ; 
      L     #ByteAddress; 
      L     L#65000; 
      >I    ; 
      )     ; 
      A(    ; 
      L     #ByteAddress; 
      L     0; 
      <I    ; 
      )     ; 
      O     ; 
      A(    ; 
      L     #BitAddress; 
      L     7; 
      >I    ; 
      )     ; 
      A(    ; 
      L     #BitAddress; 
      L     0; 
      <I    ; 
      )     ; 
      JC    END; 
NETWORK
TITLE =Create ANY pointer 

//Byte 0 of ANY pointer is the HEADER which is always B#16#10 for S7
      L     B#16#10; //Load the Byte Sytax ID B#16#10 into ACUM1 
      T     LB     0; //Transfer ACUM1 to Local Byte 0 of Temp Variable: #SourceAny Local ANY POINTER)

//Byte 1 is for DATA TYPE: 
//Types: 01=Bool, 02=Byte, 03=Char, 04=Word, 05=Int, 06=Dword, 07=Dint, 08=Real, 09=Date, 0A=TOD, 0B=Time, 0C=S5Time
      L     B#16#1; //Load the Byte data type BOOL(hex01)into ACUM1. 
      T     LB     1; //Transfer ACUM1 to Local Byte 1 of Temp Variable: #SourceAny (Type Local ANY POINTER)

//Word 2 is REPETITION FACTOR - how many items to be moved
      L     W#16#1; //Load the Word Quantity 1(hex01)into ACUM1. 
      T     LW     2; //Transfer ACUM1 to Local Word 2 of Temp Variable: #SourceAny (Type Local ANY POINTER)

//Word 4 is DB NUMBER or 0 for none
      L     W#16#0; //Load the Word Data Block Number 0 (Hex 0)into ACUM1 
      T     LW     4; //Transfer ACUM1 to Local Word 4 of Temp Variable: #SourceAny (Type Local ANY POINTER)


//Byte 8 and 3LSBs of 7 are BYTE address

      L     #ByteAddress; //Load ByteAddress from HMI into ACUM1
      SLD   3; //Shift Left Double 3 places to make room for bit level
      L     #BitAddress; //Load BitAddress from HMI int ACUM1
      +D    ; //Add 2 together to get BYTE.BIT formate
      T     LD     6; //Transfer ACUM1 to Local Double-Word 6 of Temp Variable: #SourceAny (Type Local ANY POINTER)

//Byte 6 is MEMORY TYPE
// b#16#80=I/O area, 81=Input area, 82=Output area, 83=Bit memory area, 84=Data block, 85=Instance data block, 86=Local data (L stack), 87=Previous local data
//HMI is used to select memory type then adds hex80 to put in correct format

      L     #MemType; //Load Memory type entered on HMI
      L     B#16#80; //Load hex 80
      +I    ; //Add 2 together to be proper format
      T     LB     6; //Transfer ACUM1 to Local Word 6 of Temp Variable: #SourceAny (Type Local ANY POINTER)


NETWORK
TITLE =Transfer Second ANY Pointer INPUT to Temporary Local ANY Pointer

      L     P##Dest_Any; //Load a 32 bit Area Pointer pointing at 80 bit ANY pointer (P#DB102.DBX 60.0 INT 30) from Input Variable:  
      LAR1  ; //Load Address Register One with the contents of ACUM1 (Pointer to 10 byte input variable #Dest_ANY)   

      L     B [AR1,P#0.0]; //Load the Byte Sytax ID B#16#10 into ACUM1.
      T     LB    10; //Transfer ACUM1 to Local Byte 10 of Temp Variable: #empDest_ANY (Type Local ANY POINTER)

      L     B [AR1,P#1.0]; //Load the Byte Data Type INT(hex05) into ACUM1.
      T     LB    11; //Transfer ACUM1 to Local Byte 11 of Temp Variable: #empDest_ANY (Type Local ANY POINTER)

      L     W [AR1,P#2.0]; //Load the Word Repetition Factor into ACUM1.
      T     LW    12; //Transfer ACUM1 to Local Word 12 of Temp Variable: #empDest_ANY (Type Local ANY POINTER)

      L     W [AR1,P#4.0]; //Load the Word Data Block Number into ACUM1 
      T     LW    14; //Transfer ACUM1 to Local Word 14 of Temp Variable: #empDest_ANY (Type Local ANY POINTER)

      L     D [AR1,P#6.0]; //Load the Double-Word 6 Area Pointer into ACUM1
      T     LD    16; //Transfer ACUM1 to Local Double-Word 16 of Temp Variable: #tmpDes_ANY_Ptr (Type Local ANY POINTER)

//Note: Dividing 480 by 8 removes the three right bits which specifies the bit address in the area pointer.
//Note:Area Pointer Bit Values = ZZZZ_ZZZZ 0000_0YYY YYYY_YYYY YYYY_YXXX... 
//...where Zs = Area Type (80=PI/PQ,81=I,82=Q,83=M,84=DBX,85=DIX,86=L,87=V or 00=None), Ys = Byte Value 0 - 65535... 
//...and Xs = Bit Value 0 - 7.
NETWORK
TITLE =Use System Fuction "Block Move" to move data in DB102


      CALL "BLKMOV" (//Call the System Function SFC20 BLKMOV (Block Move)
           SRCBLK                   := #Source_ANY,//To move Source Bit Destination Bit 
           RET_VAL                  := #tempRetVal,//Error code target address
           DSTBLK                   := #tmpDest_Any);

NETWORK
TITLE =

END:  NOP   0; 

END_FUNCTION
 
Is this what your looking for?

In:
MemType of INT
ByteAddress of INT
BitAddress of BYTE
DestAny of ANY which is the bit to be changed according to items entered above.

EDIT: For Dest_Any I have also passed in just M85.0 but no luck with that either.
 
If you want to copy the status of one bit, SFC20 is not the way to go. See code below.

Code:
FUNCTION FC 666 : VOID
TITLE =
VERSION : 0.1

VAR_INPUT
  MemType : INT ; 
  ByteAddress : INT ; 
  BitAddress : BYTE ; 
  Dest_Any : ANY ; 
END_VAR
VAR_TEMP
  Source_ANY : ANY ; 
  tmpDest_Any : ANY ; 
  tempRetVal : INT ; 
  iDBNum : INT ; 
END_VAR
BEGIN
NETWORK
TITLE =validate input data
      L     #MemType; 
      L     3; 
      >I    ; 
      JC    END; 
      TAK   ; 
      L     1; 
      <I    ; 
      JC    END; 
//..
      L     #ByteAddress; 
      L     0; 
      <I    ; 
      JC    END; 
//..
      L     #BitAddress; 
      L     0; 
      <I    ; 
      JC    END; 
      TAK   ; 
      L     7; 
      >I    ; 
      JC    END; 
NETWORK
TITLE =copy bit status to bit status
      L     P##Dest_Any; 
      LAR1  ; 
      L     W [AR1,P#4.0]; 
      T     #iDBNum; 
      L     D [AR1,P#6.0]; 
      LAR2  ; 
      OPN   DB [#iDBNum]; 
      LAR1  P#I 0.0; 
      L     #MemType; 
      L     1; 
      ==I   ; 
      JC    fun; 
      LAR1  P#Q 0.0; 
      TAK   ; 
      L     2; 
      ==I   ; 
      JC    fun; 
      LAR1  P#M 0.0; 
fun:  L     #ByteAddress; 
      SLD   3; 
      L     #BitAddress; 
      +D    ; 
      +AR1  ; 
      A      [AR1,P#0.0]; 
      =      [AR2,P#0.0]; 
NETWORK
TITLE =
END:  BE    ; 
END_FUNCTION
 
Thanks I'll try that out right now.
Don't know how I got lucky enough to get the evil FC number :)

I figured the 2 anypointers were overkill.
 
Thanks.
That setup works great with the RET_VAL for my trend.

Now I'm thinking about expanding the input section to allow a DB along with I,Q,M.

So I will add a number 4 to the function to:
L P# dbx0.0

Is it possible to make an input for a function optional?
I will have an input DBsrc that I only need to fill in if the memtype is 4 otherwise not needed.

I could make a dummy int, but think the program would look cleaner if just left blank?
 
To make things "optional" for a FC, you will have to go down the ANY pointer route for the area you wish to monitor. I would create a temp int called IntNotUsed and pass that in to the FC where you know it will not be used. Alternatively, you could use an FB - you can leave the parameters blank in those.

On second thoughts, just enter 0 for the DB number when you are monitoring I,Q or M instead of a variable name.
 
Last edited:
2 part question.

1. I know you've covered this before but I can't find it again.
The FC is being run but the box around the FC is a blue dotted line and not green, which makes it look like its not being processed. What causes this and how can I fix it.

2. I added in the function of monitoring a DB bit.
Are there any improvements I can make to clean this up or simplify it? There may be some improvements that can be done in the validation section I added.

Thank you greatly for you help!!!
🍻

EDIT: Figured out the 0 idea but I knew I seen blanks before, must have ben FB's

Code:
FUNCTION FC 62 : BOOL
TITLE =
VERSION : 0.1


VAR_INPUT
  MemType : INT ;    
  ByteAddress : INT ;    
  BitAddress : INT ;    
  DBsrc : INT ;    
END_VAR
VAR_TEMP
  Source_ANY : ANY ;    
  tmpDest_Any : ANY ;    
  tempRetVal : INT ;    
  DBsrcTemp : INT ;    
END_VAR
BEGIN
NETWORK
TITLE =validate input data

//Validate MemType and DBsrc
      L     #MemType; 
      L     4; //Memtype is not greater than 4
      >I    ; 
      JC    END; 

      ==I   ; //If memtype is 4 DBsrc can't be 0
      A(    ; 
      L     #DBsrc; 
      L     0; 
      ==I   ; 
      )     ; 
      JC    END; 

      L     #MemType; //If memtype is not 4 DBsrc can only be 0
      L     4; 
      <I    ; 
      A(    ; 
      L     #DBsrc; 
      L     0; 
      <>I   ; 
      )     ; 
      JC    END; 

      L     #MemType; //Memtype is not less than 1
      L     1; 
      <I    ; 
      JC    END; 

//Validate ByteAddress
      L     #ByteAddress; //ByteAddress cannot be less than 0
      L     0; 
      <I    ; 
      JC    END; 

//Validate BitAddress
      L     #BitAddress; //BitAddress must be between 0 and 7
      L     0; 
      <I    ; 
      JC    END; 
      TAK   ; 
      L     7; 
      >I    ; 
      JC    END; 
//..



NETWORK
TITLE =copy bit status to bit status

      LAR1  P#I 0.0; 
      L     #MemType; 
      L     1; 
      ==I   ; 
      JC    fun; 
      LAR1  P#Q 0.0; 
      TAK   ; 
      L     2; 
      ==I   ; 
      JC    fun; 
      LAR1  P#M 0.0; 
      TAK   ; 
      L     3; 
      ==I   ; 
      JC    fun; 
      L     #DBsrc; 
      T     #DBsrcTemp; 
      OPN   DB [#DBsrcTemp]; 
      LAR1  P#DBX 0.0; 
fun:  L     #ByteAddress; 
      SLD   3; 
      L     #BitAddress; 
      +D    ; 
      +AR1  ; 
      A      [AR1,P#0.0]; 
      =     #RET_VAL; 

NETWORK
TITLE =

END:  BE    ; 

END_FUNCTION
 
Last edited:
The block result determines the ENO status of the block. You could have the ENO true if all your parameters are good, false if one of them is bad.

Here's your block recoded. The max length of a DB is 65535 so the ByteAddress has to be passed as a word, not an int. The address arithmetic has to use the +D and not the +AR1 to be able to access byte 65535 in the DB.

The max I, Q, M depends on the CPU so I'll let you choose the limits - I've use a case statement for each memory type so you can slot in the relevant processing.

BEND is the label for a BadEND in which case the ENO will be false.

Code:
FUNCTION FC 62 : BOOL
TITLE =
VERSION : 0.1


VAR_INPUT
  MemType : INT ;    
  ByteAddress : WORD ;    
  BitAddress : INT ;    
  DBsrc : INT ;    
END_VAR
VAR_TEMP
  tempRetVal : INT ;    
  DBsrcTemp : WORD ;    
  iSFC24Return : INT ;    
  wDBLength : WORD ;    
  bWriteProtect : BOOL ;    
END_VAR
BEGIN
NETWORK
TITLE =validate input data

      L     #MemType; 
      JL    CASE; 
      JU    BEND; 
      JU    L1; 
      JU    L2; 
      JU    L3; 
      JU    L4; 
CASE: JU    BEND; 

//If memtype is 1=I
L1:   L     #DBsrc; 
      L     0; //db must be zero
      <>I   ; 
      JC    BEND; 
      LAR1  P#I 0.0; 
      JU    fun; 

//If memtype is 2=Q
L2:   L     #DBsrc; 
      L     0; //db must be zero
      <>I   ; 
      JC    BEND; 
      LAR1  P#Q 0.0; 
      JU    fun; 

//If memtype is 3=M
L3:   L     #DBsrc; 
      L     0; //db must be zero
      <>I   ; 
      JC    BEND; 
      LAR1  P#M 0.0; 
      JU    fun; 

//If memtype is 4=DBX DBsrc can't be 0 and db must be long enough
L4:   L     #DBsrc; 
      T     #DBsrcTemp; 
      CALL "TEST_DB" (
           DB_NUMBER                := #DBsrcTemp,
           RET_VAL                  := #iSFC24Return,
           DB_LENGTH                := #wDBLength,
           WRITE_PROT               := #bWriteProtect);

      A(    ; 
      L     #iSFC24Return; 
      L     0; 
      <>I   ; 
      )     ; 
      A(    ; 
      L     #wDBLength; 
      L     #ByteAddress; 
      <D    ; 
      )     ; 
      JC    BEND; 
      L     #DBsrcTemp; 
      OPN   DB [#DBsrcTemp]; 
      LAR1  P#DBX 0.0; 
      JU    fun; 
NETWORK
TITLE =copy bit status to bit status

//..validate bit address
fun:  L     #BitAddress; //BitAddress must be between 0 and 7
      L     0; 
      <I    ; 
      JC    BEND; 
      TAK   ; 
      L     7; 
      >I    ; 
      JC    BEND; 

      L     #ByteAddress; 
      SLD   3; 
      L     #BitAddress; 
      +D    ; 
      TAR1  ; 
      +D    ; 
      LAR1  ; 
      A      [AR1,P#0.0]; 
      =     #RET_VAL; 
      SET   ; 
      SAVE  ; 
      BEU   ; 
NETWORK
TITLE =

BEND: CLR   ; 
      SAVE  ; 


END_FUNCTION
 
Last edited:

Similar Topics

Hello! Is it possible to copy pointer's pointing address to any variable at Siemens step7? I mean I have pointer address to db block with...
Replies
14
Views
15,535
Hi! I use the following code (from FC) to copy words between DBs given an word offset address and nbr of words to copy. But I found out it fails...
Replies
3
Views
2,864
Hi! I modified some code, probably from member LD, to make a function element := ReadFromArray(firstElement : ANY, offset : INT) It seems...
Replies
2
Views
4,157
I have a word in some DB which I want to load to AR1 and use as a pointer. In order to do this I need to write L DBxy.DBW xy SLD 3 LAR1 I...
Replies
3
Views
533
I am trying to access the value of a pointer via OPC UA in Codesys. I can share it directly and in a struct but I cant access the value of it when...
Replies
5
Views
1,609
Back
Top Bottom