Professional Documents
Culture Documents
Page 1 of 9
PLCS.net - Interactive Q & A > PLCS.net - Interactive Q & A > LIVE PLC Questions And Answers > Transfer
AnyPointer To FC in Step 7
PDA
Hello,
I am currently building an FC which calls SFC21 "BLKMOV" from inside it :
CALL "BLKMOV"
SRCBLK :=#PriSec_AnyPointer
RET_VAL:=#Retun_Value
DSTBLK :=#Jokan_PriSec_AnyPointer
I would like to have the source and destination blocks dynamic, in the sense that the can be entered as inputs
to my FC. I've tried declaring inputs of type "Any" and passing them into my FC. I've then tried plugging them
directly into "SRCBLK" and "DSTBLK" but Step7 will not except them. I keep getting the error : "Declaration
range of the actual side VAR_INPUT does not fit the formal declaration range VAR_OUTPUT of the formal
parameter DSTBLK"
Any ideas on what I'm doing wrong?
Any help would be greatly appreciated...thank you kindly for your time
Cheers,
R.K.
SimonGoldsworthy
Rusty_K
Hi Simon,
Thank you kindly for your reply. Yes, this is what I am currently doing..I was wondering if it was possible to
avoid all this and simply enter the anypointer as an input to the FC and plug that in directly to the BLKMOV
function found inside my FC.
Based on the approach you took, I'm guessing this is not possible..am I right to assume this? Is there any
reason why it cant be done?
Thanks again for the help
R.K.
SimonGoldsworthy
If you are going to use any pointers then why not just call SFC21 with the any pointers ? Maybe I'm missing
something here ?
If you want to pass an any pointer on it is possible but needs carfeful consideration, have a look at this post for
example:
http://www.plctalk.net/qanda/showpost.php?p=169469&postcount=8
http://www.plctalk.net/qanda/archive/index.php/t-25919.html
26/06/2015
Rusty_K
Page 2 of 9
SimonGoldsworthy
What I mean is call SFC21 instead of calling your FC. What I don't get is why you need to create your FC.
Rusty_K
Oh, sorry for the confusion! My FC is doing a lot more than just the block move..it's comparing ASCII characters,
setting outputs etc. I use the block move to index values in a DB.
Cheers!
R.K.
S7Guy
I'm guessing that he has other code in his FC, which would make it handy to use dynamic pointers.
In any case Rusty, you will have to move the FC input variables to local variables, and then it will work. I do that
all the time. Here is an example (Source and Destination are local ANY variables; the other variables are you
inputs to the FC):
L P##InputPointer
LAR1
L P##Source
LAR2
L D [AR1,P#0.0]
T LD [AR2,P#0.0]
L D [AR1,P#4.0]
T LD [AR2,P#4.0]
L W [AR1,P#8.0]
T LW [AR2,P#8.0]
L P##DestinationPointer
LAR1
L P##Destination
http://www.plctalk.net/qanda/archive/index.php/t-25919.html
26/06/2015
Page 3 of 9
LAR2
L D [AR1,P#0.0]
T LD [AR2,P#0.0]
L D [AR1,P#4.0]
T LD [AR2,P#4.0]
L W [AR1,P#8.0]
T LW [AR2,P#8.0]
CALL "BLKMOV"
SRCBLK :=#Source
RET_VAL:=MW10
DSTBLK :=#Destination
There are many ways to do this, but this is pretty straight forward.
Rusty_K
SimonGoldsworthy
Just posting this when I saw S7Guy had also posted ! Dont forget to save AR2 if any of this code has been called
from a function block higher up.
FUNCTION FC 1 : VOID
TITLE =pass on any pointers to sfc20
VERSION : 0.1
VAR_INPUT
pSource : ANY ;
pDestination : ANY ;
END_VAR
VAR_OUTPUT
sfc20Return : INT ;
END_VAR
VAR_TEMP
pSrc : ANY ;
pDest : ANY ;
dwtar2 : DWORD ;
END_VAR
BEGIN
NETWORK
http://www.plctalk.net/qanda/archive/index.php/t-25919.html
26/06/2015
Page 4 of 9
Ken M
And as a late tailpiece, the reason you can't do it by simply passing the name of the input parameter is, to quote
the STEP7 manual,
"STEP 7 restricts the assignment of formal parameters of an FC as actual parameters for the formal parameters
of a different FC. You cannot, for example, assign parameters with complex data types or a parameter type as
the actual parameter."
So there you have it. Clear as ... well, clear as you'll find in a Siemens' manual anyway.
As far as I can see you should be able to do it with 'simple' data types declared as parameters (INT, BYTE,
WORD etc) but passing on 'complex' parameters (ARRAY, ANY, POINTER etc) is strictly verboten.
Regards
Ken
Rusty_K
http://www.plctalk.net/qanda/archive/index.php/t-25919.html
26/06/2015
Page 5 of 9
sryan
Hey guysDon't know if anybody's still monitoring this, but I've got a question: does anybody know *why* you can't pass
on a formal parameter of "non-elementary" type? I can't for the life of me think of a good reason, since it will
pass a local variable of the same type, and it makes things difficult (though not impossible) when writing a
library of functions that operate on complex data types. Guess I should be used to the power of Step7 by now...
Anyway, thanks for the explanation, Ken- yours was much more straightforward than the manual's.
Steve
gregoryg
Elementary data types are passed to FC with their values located in the local data of calling block (you can check
this by L P##parameter), complex data types are passed as pointers (also located in local data of calling block).
Internally Step7 translates access to complex data type for ex. structure to something like this:
You are writing:
L Structure.Element // Element is Word type
PLC executes:
OPN DB xxx // if Structure is located in the DBxxx
LAR1 StructureStartingAddress
L W[AR1,P#Y.0] // Y is offset to Element from StuctureStartingAddress.
Thats why complex parameter types cannot be passed.
L D[AR2,P#0.0]
dahnuguy
and the simple answer is.....................no you cant do that with Step7,
but we have a variety of workarounds if you are fond of making something that seems simple into something
quite complex.
S7 has STL because it would be impossible to use without it.
It's like the programer for S7 one day just stopped and said, "Oh gezz just write it yourself if you want it to do
something more."
dahnuguy
Just posting this when I saw S7Guy had also posted ! Dont forget to save AR2 if any of this code has been called
from a function block higher up.
FUNCTION FC 1 : VOID
TITLE =pass on any pointers to sfc20
VERSION : 0.1
http://www.plctalk.net/qanda/archive/index.php/t-25919.html
26/06/2015
Page 6 of 9
VAR_INPUT
pSource : ANY ;
pDestination : ANY ;
END_VAR
VAR_OUTPUT
sfc20Return : INT ;
END_VAR
VAR_TEMP
pSrc : ANY ;
pDest : ANY ;
dwtar2 : DWORD ;
END_VAR
BEGIN
NETWORK
TITLE =source any pointer
TAR2 #dwtar2; //save ar2
L P##pSource;
LAR1 ;
LAR2 P##pSrc;
L W [AR1,P#0.0];
T W [AR2,P#0.0];
L W [AR1,P#2.0];
T W [AR2,P#2.0];
L W [AR1,P#4.0];
T W [AR2,P#4.0];
L D [AR1,P#6.0];
T D [AR2,P#6.0];
NETWORK
TITLE =destination any pointer
L P##pDestination;
LAR1 ;
LAR2 P##pDest;
L W [AR1,P#0.0];
T W [AR2,P#0.0];
L W [AR1,P#2.0];
T W [AR2,P#2.0];
L W [AR1,P#4.0];
T W [AR2,P#4.0];
L D [AR1,P#6.0];
T D [AR2,P#6.0];
NETWORK
TITLE =block move
CALL "BLKMOV" (
SRCBLK := #pSrc,
RET_VAL := #sfc20Return,
DSTBLK := #pDest);
NOP 0;
NETWORK
TITLE =restore ar2
LAR2 #dwtar2;
END_FUNCTION
This is beautiful and a good example of the need for STL in S7, even when using "LAD" for your main program.
I was attempting a similar idea in LAD using the "MOV" command with no luck.
http://www.plctalk.net/qanda/archive/index.php/t-25919.html
26/06/2015
Page 7 of 9
I could never figure out how to get the variable into the block and then assign it to SFC20.
I see now more and more that S7 is really STL from the beginning.
It took me a fe minutes to see what you were doing, I wasn't looking closely at first, but now I get it.
So is it fair to say the reason this must be done this way is beacause of the limit on how much will fit into the
registers?
Is that why you have to move each byte one at a time from LAR1 to LAR2?
Why can't you just load the whole thing at once is my base question.
Load all bytes of AR1 into AR2?
I don't use STL but something like this
L AR1 all
T AR2 all
Instead of load and transfer 0.0 to 0.0 and then 2.0 to 2.0 etc.
L D[AR2,P#0.0]
Any ANY pointer is 10 bytes long. The accumulators are 4 bytes long.
The any pointer is formatted as follows:
id/type - 1 word
length - 1 word
DB number - 1 word
Area pointer - 1 double word
hence the sequence of load/transfers. Important note: Ar1 and Ar2 point to the data
dahnuguy
;303170']
Important note: Ar1 and Ar2 point to the data
What do you mean by this?
they point to the data?
AR1 and AR2 are your holding registers for doing multi step operations, correct?
So are you saying that the data is not moved into AR1&2?
Thim
If i remeber well the AR are the position of the data and the accu is where the data is but i'm sure LD will correct
me if i'm wrong :-)
Example
LAR1 P#[X.Y] //Example Lar1 P#4.0
Opn db1
L Dbw[AR1,P#0.0] // L DBW4
Then you would open db1.DBW[X.Y] no data only positions
RMA
I'm monitoring the commissioning of a new project at the moment and the sub-contracters concerned have a
very structured approach to programming that I think S7Guy would approve of. However, most of their
http://www.plctalk.net/qanda/archive/index.php/t-25919.html
26/06/2015
Page 8 of 9
programming is done using FBs, in this case over 400 against 29 FCs.
Of these FCs about half are so-called "Typicals" for all sorts of basic functions, including simple and redundant
measured value handling. These "Typicals" are then repeatedly called from within the FBs that make up most of
the program.
I've already had a couple of cases where they've been using fully qualified DB-addresses as parameters for the
FC call and then trying to access the data directly instead of laying it onto a TEMP and accessing the TEMP - no
great problem, fairly quickly spotted and solved.
Now I've got what feels like a related, but not quite identical, problem and I'm a bit puzzled.
Here's the calling FB and as you can see they're passing over a pointer to the start of the UDT for this particular
measurement.
Oops, the facility to insert pictures in the middle of text seems to have disappeared, so both the calling FB and
the called FC are appended as attachments.
Now what's confusing me is that according to Berger in chapter 19.3 it is permissible to pass on a UDT as an
actual parameter. However, in table 19.5, which details what can and can't be used as parameters under the
various possible calling conditions, in the case of an FB calling an FC, it's permissible to pass over a UDT for an
IN or an OUT parameter, but not for an IN-OUT parameter.
The other thing that bothers me is that, in my opinion, they are not passing over a UDT itself, but rather an
ANY-Pointer pointing to the instance UDT for this particular measurement - and that brings us back to where this
Thread started!
Just to confuse the issue further, so far we've tested about half-a-dozen measurements and this is the first one
to cause problems.
Can any of the "usual suspects" throw a bit of light on whether or not this is an acceptable practice, or whether
it's just luck that it's worked so far?
Manglemender
Ken,
If my understanding is correct, table 19.5 describes what can be passed on to another function inside the called
block. Passing a UDT into an FC and then using it would be OK i.e. if a udt was declared as INOUT as UDT_Data
the in your code you could refer to #UDT_Data.Item but you couldn't then call another block and pass
#UDT_Data as an argument to the called block.
Nick
RMA
L D[AR2,P#0.0]
The other thing that bothers me is that, in my opinion, they are not passing over a UDT itself, but rather an
ANY-Pointer pointing to the instance UDT for this particular measurement What makes you form this opinion Roy ?
RMA
I think I was just having a bit of a terminology problem, probably compounded by having to work in German. As
http://www.plctalk.net/qanda/archive/index.php/t-25919.html
26/06/2015
Page 9 of 9
a result I went and had a closer look at the code and have just discovered that they've got two successive calls
fed with the same pointer, so the data from the second call is simply overwriting the data for the first call (which
happens to be the measurement we were looking at).
So it looks as though everything is OK, now that I've studied the program in detail I understand how (and more
to the point, after reading and re-reading Berger, why) it works. I was just getting a bit trigger-happy after the
previous fully qualified DB parameter incidents.
Edit: Oops, spoke too soon, I hadn't moved the mouse out of the way before scrolling from one network to the
next one, so in fact the addresses are OK.
Back to the original problem, why isn't this one working? Guess I'll need to go and take a closer look at exactly
what's happening.
Manglemender
Wrong Scotsman Nick!
Cheers
Roy
LOL
When I first read that I thought "How does he know I'm a Scotsman?" Then I realised my mistake - sorry about
that Roy.
Nick
RMA
Just to finish off the story, apparently (the problem was solved by the time I got back) the problem was an IN
with the raw value from the PEW being declared as a WORD instead of an INT. The program was basically
written in Function Block and data type checking was turned on. A small part of the program, checking whether
the incoming signal is between 20 and 24 mA (ie differentiating between too high a signal and wire break) is
written in STL and the INT compare wasn't working properly. The other signals which had been basically tested
were by chance in the normal range, so that the problem didn't show up.
.
http://www.plctalk.net/qanda/archive/index.php/t-25919.html
26/06/2015