S7 - Converting an INT to Byte.Bit Pointer Format

RMA

Member
Join Date
Sep 2004
Location
North of Hamburg, Germany
Posts
2,052
Has anybody got a routine handy that will take an INT as input (1 - 21) and convert it to the Byte.Bit format that is needed to add to a basic Pointer Offset to access a list of BOOLS in a DB.

At first I thought it was going to be easy using
L #Module_Nr
L1
SLD

or something similar, but of course that only works up to 7, never mind the problems relating to Byte position in the DWORD! I'm sure there must be a relatively elegant way to achieve this, but I'm blowed if I can think of it! :oops:

Just thought about it a bit more.

If the worst comes to the worst I suppose since I've only got to go up to 21, I could always break it down into Bytes to use the SLW instruction and adjust the Pointer starting position accordingly. Doing that 6 times is a bit much spaghetti though, even for me! So if anybody has any better solutions, I'm still in the market!

Edit:

Further thoughts, If I divide the the Module Number by 8 and save the remainder somehwere, then I've got my Byte address in AKKU1 Low. Then clear AKKU1 High and I've got the Basis for my Pointer, SLD3 and add the remainder, ought to do it, or have I forgotten something?

Off to check the STL handbook and see if my memory is serving correctly on how /I works.
 
Last edited:
Too much of a good thing?

Don't know exactly what you are trying to do.

If you have 21 bits stored in 1 dword, and want to read 1 bit,
loading a l#1, then shift it x times (x=1-21) and mask the Double word with that, should get you close (still 32 bits in a DWord, so you have 11 left right).

Anyway, I do have a routine that can read/write arrays of anything (including single bits). But as the title sugest, this routine may be way to much for what you want to do. (Plus I haven't really documented it much). Principle of this block (FC) is, provide two ANY variables (One two indicate start location of array, one to point to value to read/write) and an offset. Use some STL and block copy command to read/write one unit of the value type (Bit, Byte,Struct etc.. any type below 16) to/from the location given by the array pointer plus the offset. So if you have an array of bools in a DB, you can read write any bit by providing the FC with
DBxx.BOOL[0] for the array, m100.0 for the bit, and your integer for the offset (offset from zero, which in this case equals index, since array starts at 0).

Reading/writing individual bits was alittle more complicated then the other data types, since the block copy command insists on reading/writing 8 bits at the time (as documented), plus the pointers need to be on a byte boundary (not documented in my "old" manual).
 
Are you making this more complicated than it needs to be?

It appears that you want to take an Integer (1-21) and then make that into an Offset value, apparently, in a Double-Word Offset Value.

How about first deciding on your double-word location... let's say V100 and V101. Then Load a "0" into V100(MSW) and V101(LSW).
(MSW = Most Significant Word, LSW = Least Significant Word)

Then "AND" your Integer (1-21) with V101(LSW).

Now V100/V101 = your Integer (1-21) in Double-Word format.

Is it more complicated than that? If so, then there is something that you are not telling us.

You've indicated some of your thoughts about the problem... but... they just don't seem to follow your stated over-all intent...

Something is missing... what are you not telling us?
 
Hi Roy,

as USDutchman wrote:
Don't know exactly what you are trying to do.

You have a INT wich contains a Bitindex ( 1 - 21 ) and
you will add this index to a Basic-Pointer ?

If so , there is no need for SLD or convert to Byte.bit.
( If not ?? ignore this post ;) )

[Sample :]

FUNCTION FC 15 : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
in_PDatabase : ANY ; // Sample P#DB15.dbx0 Byte 1
in_iBitoffset : INT ;
END_VAR
VAR_OUTPUT
out_Result : BOOL ;
END_VAR
VAR_TEMP
P : STRUCT
Kenn : BYTE ;
Typ : BYTE ;
lenght : WORD ;
DBnum : WORD ;
Bereich : DWORD ;
END_STRUCT ;
END_VAR

BEGIN
NETWORK
TITLE =Copy Pointer in local structure

L P##in_PDatabase; // Any-Pointer
LAR1 ;
L B [AR1,P#0.0]; // ID S7
T #P.Kenn;
L B [AR1,P#1.0]; // Data Typ
T #P.Typ;
L W [AR1,P#2.0]; // Lenght
T #P.lenght;
L W [AR1,P#4.0]; // DBno
T #P.DBnum;
L D [AR1,P#6.0]; // Area
T #P.Bereich;

AUF DB [#P.DBnum]; // open Datablock
//************************************************
//add Bitoffset to pointer
//************************************************
LAR1 #P.Bereich; // Area --> AR1
L #in_iBitoffset; // INT add Bit Offset
+AR1 ; // to -> ar1

U DBX [AR1,P#0.0]; // Sample ?=1
= #out_Result; // Test if function work


END_FUNCTION

[/Sample]

You can easily add the INT ( 1-21 ) to AR1.

For example, if you type in L P#10.0, then the Status
shows &H50. That are 80 Bits. The SLD 3 are only needed
if you add bytes or words to pointers.



Regards
Rolf
 
Roy,

I’ll take a shot too. :)

If I understand you correctly, you want to correlate an integer value with a bit and then calculate a pointer based on the bit position, right? For instance, if someone enters 19, they mean the nineteenth bit from the right in a doubleword, which would be bit DBX1.2 in DBD0, creating a pointer of P#1.2. Is that right?

If so, I can think of a couple of ways, but if you are certain that you will not use more than 32 values, then I would suggest using the CAD instruction. The CAD instruction swaps the bytes of a doubleword so that bytes 0, 1, 2, 3 become 3, 2, 1, 0 without affecting the bools within the bytes. So, you end up with a very linear order of bits from which a pointer can be calculated.

Code:
      L     0
      T     #Index
      L     DB10.DBD    0
      CAD   
top:  SRD   1
      JP    ar
      T     #Shift
      L     #Index
      +     1
      T     #Index
      L     32
      ==I   
      BEC   
      L     #Shift
      JU    top
ar:   L     #Index
      LAR1

The local variable #Index is an INT, and #Shift is a DINT. My example starts at DBD 0, but if you use a higher address, the code will still return a pointer between P#0.0 and P#3.7. I don’t know what you want to do with this, so you may have to add this pointer to the offset of whatever dword you are reading from.

Then again, maybe you meant something completely different.
 
If I understand you correctly, you want to correlate an integer value with a bit and then calculate a pointer based on the bit position, right? For instance, if someone enters 19, they mean the nineteenth bit from the right in a doubleword, which would be bit DBX1.2 in DBD0, creating a pointer of P#1.2. Is that right?

That's exactly what I want and yes, as those familiar with my project from other posts will know, I don't need to go outside the 32 Bit boundary, so the CAD command is the answer to this maiden's prayers! :geek:

I think I vaguely remember noticing the existence of this command somewhere along the line, but I'd forgotten about it - it then only required a further 5 minutes to discover that it's TAD in German! (T for "tauschen" to swap).

The end result definitely meets my definition of elegance, as far as that's possible in STL!

What I'm using it for is to check in a loop if one of the 21 modules has been selected or not (this is held in a row of BOOLS in the middle of the Menu DB). If it has been selected I then need to check its delay time, held further down the same DB and if it's = 0 increase it to 1 (which = 10µs delay which is irrelevant). This is because the timers in the FM352-5 don't fire if you have a delay time = 0, since I only need 100µs accuracy, the 10µs is insignificant. Conversely, if the Module has not been selected I set the delay = 0, which prevents the trigger for that Module from firing.
 
Last edited:
Hi S7Guy,

Just finished packing everything up for shipping and came back to have a look at the INT to Pointer conversion.

Maybe I'm a bit slow today, but there are a couple of points I'm not quite clear about:

What have you got in DB10.DBD 0, is that the INT, or is that the Base Address of the DB where you're extracting the BOOLs (corresponds to my Menu/Recipe DB)

If it's NOT the INT, where are you picking it up - I'm passing it over in an IN parameter called #Module_Nr.

IF it IS the INT, can you explain what you're doing with the JP instruction.

Ahh, a light glows dimly, could it be that in DB10.DBD 0 you've got the result of my:

L #Module_Nr
L 1
SLD

which you are then turning round with the CAD instruction to get back to the proper Bit position?

If so, then we're nearly there. The only thing that's left is how to couple the contents of AR1 to the Base Pointer to my "Select" Bits which start at DB4.DBX0.1 (for Module 1).

Have to go and start searching through my Pointer examples. I've done this a few times now, but for some reason I can't get the details locked in my head. I always need the examples in front of me.

Cheers

Roy
 
Last edited:
Terry Woods said:
Are you making this more complicated than it needs to be?

Having just finished getting S7Guy's offering adapted and integrated in my program, I've come to the conclusion - Yes, I am! :oops:

This is a result of going about things from the wrong end.

I got myself fixed on converting my Module Number to a Pointer to access the BOOLs in the DB representing the "Select" Bits for each Module. But all I actually needed to do was to set a Pointer to the start of the BOOL area, in this case P#DB4.DBX 0.0 and since the Module Nr. is an INT I can just add it directly to get the Offset i.e., the Module Nr. is the Offset!

Since in all my DBs where I'm handling BOOLs on a Module Basis, I've always used DBX0.1 for Module 1, DBX0.2 for Module 2 etc., leaving DBX0.0 either as a Dummy or as a general Flag for something else, I don't even need to adjust the Offset.

Still, I'm quite pleased it went this way, as usual, I've learnt a load from fathoming out how the suggestions people made were working - wasn't always so easy! And in particular, I've been reminded of the existance of the CAD/TAD command, which is something I'm sure I'll be using again.

Thanks once again to all who offered suggestions.

Cheers

Roy
 
I guess I partially misundertood you Roy, but the concept of using CAD is still valid, and it looks like you got it working. If not, post away and we'll jump on it. :)

And yes, if you could do the whole project all over again, you would probably do some things a little differently. From what I read about your project, it begs for some kind of object-oriented style of programming where all of the properties of a station are grouped together in a udt, just so you can avoid problems like the bool pointer. That said, I doubt if any of us has finished a project and not said at least once, "Damn, I wish I had done that part a little differently....." I know I do it all the time.
 
I guess I partially misundertood you Roy

No you didn't misunderstand me, I made the mistake of looking at my problem, coming up with a (wrong) solution and then asking for help to implement my solution.

What I should have done was ask for help to solve my problem.

Sometimes you can't see the wood for the trees!

This has been my first major project alone. Up till now I have mainly been involved as part of a team, where they would usually throw the HMI stuff at me because, with my DCS background, I found that all dead easy, but as a result, I didn't learn as much actual programming as would have been normal in that amount of time. Before this I've only done one, very small, project entirely on my own, and I cringe when I think back to it! Although I did get it working fairly quickly in the end, it was full of the usual beginners problems of double coils etc.

The major blessing on this project has been the time scale. As a result I've been able to undergo an enormous learning curve (which has accelerated even more in the five months since I found this site!), without being under too much pressure - up till now that is! The crunch is about to come, I'll be on site most of next week starting to commission the Interlock system - probably with no internet access. :(

Thanks once again to all who have helped me get this far! :site:
 
Roy,

I’ll take a shot too. :)

If I understand you correctly, you want to correlate an integer value with a bit and then calculate a pointer based on the bit position, right? For instance, if someone enters 19, they mean the nineteenth bit from the right in a doubleword, which would be bit DBX1.2 in DBD0, creating a pointer of P#1.2. Is that right?

If so, I can think of a couple of ways, but if you are certain that you will not use more than 32 values, then I would suggest using the CAD instruction. The CAD instruction swaps the bytes of a doubleword so that bytes 0, 1, 2, 3 become 3, 2, 1, 0 without affecting the bools within the bytes. So, you end up with a very linear order of bits from which a pointer can be calculated.

Code:
      L     0
      T     #Index
      L     DB10.DBD    0
      CAD   
top:  SRD   1
      JP    ar
      T     #Shift
      L     #Index
      +     1
      T     #Index
      L     32
      ==I   
      BEC   
      L     #Shift
      JU    top
ar:   L     #Index
      LAR1

The local variable #Index is an INT, and #Shift is a DINT. My example starts at DBD 0, but if you use a higher address, the code will still return a pointer between P#0.0 and P#3.7. I don’t know what you want to do with this, so you may have to add this pointer to the offset of whatever dword you are reading from.

Then again, maybe you meant something completely different.

I came across this post as I am trying to do the same thing. I have read the posts (and learned new things :p), but besides that I would like to ask a qyestion about the following piece of code:

L P##Variable
L #Int
+D
LAR1

Here I am adding an integer to a pointer. At the end I get exactly what is discussed in the previous posts, an offset for bits. But in online mode I see that the sum is a negative value. Could this cause any problems? I know I am summing two totally different types of variables (don't even know how this came up to my mind), but in the end it works.

I am just suspicious about getting negative values.

If anyone could give their opinion, I would appreciate it.

Kind regards.
 
What exactly are you looking at when you see that the sum is a negative value ?
A pointer consist of 6 bytes, and the order of the various bits does not align with a normal INT or DINT. So it is possible that the sign bit of the DINT or INT you are looking at is actually part of the byte address for example.
 
What exactly are you looking at when you see that the sum is a negative value ?
A pointer consist of 6 bytes, and the order of the various bits does not align with a normal INT or DINT. So it is possible that the sign bit of the DINT or INT you are looking at is actually part of the byte address for example.

I am looking at the "+D" line. Yes, you are probably right, it is about sign. Didn't think about that.

Thanks for answering, Jesper.
 
(for the sake of correctness)

My advice was correct, but my argumentation was wrong.
The way the pointer is programmed, it is a 4-byte address, not a 6-byte as I wrote.

If the pointer is addressed with an area-crossing address (i.e. P#M30.0) rather than an area-internal address (i.e. P#30.0) then this is indicated by the left-most bit being set to 1. That appears as a negative value when you look at the pointer as a DINT.

edit: "left-most" instead of "1st" bit.
 
Last edited:

Similar Topics

We just completed the conversion of a PLC 5/80 to a 1756-L8x processor. The old 5 program had numerous MSG instructions sending data to/from...
Replies
24
Views
9,412
I am having problems expressing an ANALOG OUTPUT 16bit INT word (0-10V Proportional Valve Voltage) as a REAL decimal number. From my...
Replies
6
Views
9,118
Is there anyway to convert a BOOL to a INT (DINT or SINT) in ladder logic. I am working in RSLogix5000 and am attempting to count 4 Discrete...
Replies
3
Views
5,483
I have 3 values. DINT values. They make a product number when assembled together. D: DINT; L: DINT; H: DINT; The variables D, L and H are...
Replies
6
Views
6,611
I am using an AB Micrologix 1200 that contains a counter with a destination of a floating point number. The number can get very large so I need...
Replies
8
Views
8,397
Back
Top Bottom