Siemens S7-300 Indirect addressing

mr_sleepy

Member
Join Date
Nov 2010
Location
Carnoustie
Posts
36
I have spent a couple of weeks now hunting around for information to step7 indirect addressing. There are many, many discussions relating to this subject but none of them quite answer my question specifically so here goes.

I am programming up a recipe function for a new project which involves doing a dynamic lookup of db address areas and then using a block move function to copy recipe params to a working area. I did a sample of 2 or 3 recipes to prove my basic concept was sound so now i want to roll it out to 30 or more. My first option is to copy the 5 or 6 lines of code generated for 2 or 3 recipes and hand modify them to add the extra lines of code but i wanted it to look neater and more graceful than that. This led me once again to indirect addressing for s7. By using the block move function i have cornered myself a little in the restriction of using the any pointer. What i have been looking at is any pointer maths so i can modify the index of the lookup on the fly to find the block of data relevant to the recipe being called.

For reference my any pointer on the block move looks like this p#db351.dbx500.0 word 500. My first job was too find out what the elements of the pointer were so after a bit of googling i found how to export the pointer elements like so

L P##pntrin (i just pass the initial pointer as an input to the fc)
LAR1
L W [AR1,P#0.0]
T MW 1500
L W [AR1,P#2.0]
T MW 1502
L W [AR1,P#4.0]
T MW 1504
L D [AR1,P#6.0]
T MD 1506

then with my element data safely contained in 'real' memory locations i studied its contents to work out the indexes and got this

mw1500 = address type/pointer header
mw1502 = no of data to transfer
mw1504 = datablock number to look up
mw1506 = 0x84 + 000000 where 000000 = address offset * 8 + bit no (0 in my application).

So to get the dynamic pointer i thought it should be easy to do some basic math on these values, load them back into the pointer and then call it on my block move. My code so far is

L P##pntrin (same here, passed the pointer as a parameter)
LAR1
L DW#16#84000000
T #Temp
L "Menu_Display_Data".Menu_Current_Selection
L 1
-I
L L#500
*D
L L#8
*D
L #Temp
OD
T #Temp
T D [AR1,P#6.0]
TAR1

So for clarity what im doing is leaving all the other elements of the pointer as is and modifying only the double word pointer that references my address in the chosen datablock. The hex header of 0x84 stays the same hence the 2 double words getting or'd together.

The first problem is im not really understanding what happens to begin with, ar1 & ar2 are both 32 bit registers, or so im led to believe, but right at the start my instruction l##pntrin loads the any pointer into accu1 which i then transfer into ar1. If my understanding is correct the temp variable pntrin of type any takes up 10 bytes which is 2 bytes longer than ar1 + ar2 when i do the instruction L D [AR1,P#6.0] to get the elements where is the address that im actually looking at? It works because the correct data goes into accu1 and then onwards to my md1506 but i dont know why.

The second problem is that once i modify the double word to contain the value i want to use i can load it back into ar1 as in T D [AR1,P#6.0] but then the subsequent tar1 instruction puts the pointer back to accu1 (i think) but then i try to do T P##pntrin or any other 'any' variable and the compiler doesnt like it. So now im stuck, im either trying to assign the modified pointer to an 'any' variable and using that for the blkmov(sfc20), or im using the ar1 as an input for the blkmov in stl. At least i think thats what im trying to do.

Edit** After reading this post again the other thing i thought about doing was declaring the any pointer as a variable, passing it an external value (which im already doing) and then using the ar1/ar2 to load a local indirect pointer (l#0.0?) and modifying the local data stack this way. Is that possible?

Many many thanks in advance to anyone who feels clever enough to tackle this perplexing problem on a monday morning.
 
From your coding it would appear that your 30 or so recipes start at db351.dbx500.0 and each recipe is 500 words long. You wish to copy a selected recipe into a defined area - is that correct?

Let's worry about the detail of the anypointers etc. once we have a clear understanding of what you want to achieve.
 
I just figured it out :D Im busy sorting the project out just now but i will try and post an outline solution to what i did. Maybe it will save others some hassle.

Basically i created a temp variable in an fc of type any and assigned the parameters to it by using the local data stack offsets to accomplish the task (makes a big sigh of relief)
 
Good, note that your arithmetic for calculating the base address for each recipe is incorrect as you have 500 words per recipe and your arithmetic is for 500 bytes per recipe.
 
Ye, im just after fixing that :|
When i did a course on siemens many moons ago the tutor always said, watch out when addressing in siemens, because it may byte you.
lol, well i did anyway...
 
Method for modifying an any pointer (type 3) to allow dynamic adjustment of the paramters

I have been searching for the way to do this for a while now and whilst i think i might have had all the individual
pieces of knowledge previously i hadnt made the 'jump' and glued them together. So for anyone who is searching for a way to make
a dynamic any pointer in a step 7 function block here goes.


Step 1 - Siemens documentation about the composition of the any pointer is quite confusing so first you need to investigate the
makeup of the pointer that you want to use. For me the easiest thing to do was to make a new function block with 1 input of type any.
For my example i will be calling the input pntrin.

Step 2 - Now that you have the any pointer declared, the next step is to write the code that will output the components of it for
external analysis. You need to find an area of flags or db that is free and modify the following code to suit. I will be writing my
data to 10 bytes starting from mw1500. The code is as follows (make sure you are programming in stl)

L P##pntrin
LAR1
L W [AR1,P#0.0]
T MW 1500
L W [AR1,P#2.0]
T MW 1502
L W [AR1,P#4.0]
T MW 1504
L D [AR1,P#6.0]
T MD 1506


Step 3 - Next you must call the new block in your program and pass it the value of the pointer you want to dynamically assign. In
my example i will be using p#db350.dbx0.0 word 500. It will be broken down for analysis like so

db350 - data block number - element 1
dbx0.0 - starting address - element 2
word - datatype - element 3
500 - data quantity - element 4

Step 4 - Load the newly created block and then the block that calls it. I always find it easiest to load these things into ob1 if its
just for a temporary job.

Step 5 - Fire up your monitor/modify vat table and punch in the address's where you previously transferred the contents of the any pointer
to. It should contain numbers that look like this (unless you are going for a different pointer type)

mw1500 = w#16#1004 Pointer header (dont change this)
mw1502 = w#16#01f4 (or 500 decimal) This is the number of data to transfer - element 4
mw1504 = w#16#015E (or 350 decimal) Datablock offset number - element 1
md1506 = dw#16#84 000000 - address offset/starting address - element 2

So now you have the exported elements. Now its time to construct a pointer with dynamic address's

Step 6 - Start by modifying the block you created in step 1. Add another pointer but declare it in the temp variable area. This
step is particularly important because the temp area uses local data which we are now going to utilise. I will call the pointer any_temp

Step 7 - Assuming the any pointer variable you just declared in the temp area of the function is the first declaration you should now
add some code like this (again in stl) Im using another free area of data in the plc of 10 bytes starting from mw1510 for this example

L MW 1510
T LW 0
L MW 1512
T LW 2
L MW 1514
T LW 4
L MD 1516
T LD 6

step 8 - Now you have the constituent parts of your dynamic any pointer. Its time to assign some values to make it do some work. To
use the dynamic pointer you assign data in the following way

mw1510 = w#16#1004 same as header from step 5
mw1512 = w#16#01F4 - element 4 from step 3 (or any other data quantity you require)
mw1514 = w#16#015E - element 1 from step 3 (or any other datablock number you require)
md1516 = dw#16#84 + address offset

The make up of the last part is quite important so follow these steps to get the correct address

move dw#16#84000000 into a free variable (best done in the local temp data of the function)
Calculate the address offset as follows start address * 8 + bit number
for example if i want to start at 500.0 it would be 500 * 8 + 0 = 4000 (make sure you use double int maths functions here)
now you need to glue the 2 parts of the address together so use a double or word instruction to get them both together
now move them into the correct variable location for the any pointer (md1516 in my example)

N.B you need to take into the account the number of bytes used in any given data type when performing address offset calculations e.g 1 word = 2 bytes 1 dword = 4 bytes . For clarity it means whilst you can move 500 words from 1 block to another the starting address for the next block of 500 words is actually + 1000 bytes

step 9 - Lastly you need to call a block move and use the pointer inside the function to do the intended work. All you need to do is
modify the contents of the markers m1510 to m1519 and call the code in step 7 before you call the pointer to get the correct any
pointer location.

Thats it hopefully this has given you some insight and ideas about how to do your own dynamic any pointer. I dont claim this guide to be
100% or foolproof but if it saves you some of the hassle i had then it must be worth it. Enjoy.
 

Similar Topics

Hello all. I have an ESA HMI that is connected to a Simatic S7-300 (CPU312). I have uploaded the program from the PLC which is written with Step7...
Replies
6
Views
1,450
Hello. There is a problem with Siemens S7 300. We got a replacement PLC but it does not run the program from the MMC. The new PLC is dated 2011...
Replies
3
Views
691
Hi to all, Our company does not usually use Siemens PLCs, but have a press with one in it. We are trying to change the IP address in our Simatic...
Replies
2
Views
1,070
G'day guys, I am setting up a s7-300 as a test rig for the workshop and when I downloaded the PLC is not going into run mode, I keep getting a...
Replies
35
Views
5,227
I am trying to write just MSEC to S7 300 Controller date/time using OI.SIDIRECT Aveva communication driver? The old HMI (WINCC) tag is assigned...
Replies
1
Views
1,060
Back
Top Bottom