Pointer Problem??

INST

Level-2
Beiträge
272
Reaktionspunkte
15
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

habe euch ein kleiner Teil eines Programmes hier her kopiert und bräuchte hierbei euere Hilfe, weil ich das nicht ganz verstehe.
Ich denke, das hat was mit Pointerprojektierung zu tun z.B. L 2.0, A [DBD 30], usw.

Ich wollte im dem Programm einen Ausgang suchen und habe ihn aber leider nicht gefunden. Irgendwie sind die Ein- und Ausgänge direkt in einem DB abgelegt. Wie funktioniert das??

Mit Pointerprojektierung und indirekte Adressierung habe ich noch keine Erfahrung bzw. noch nie selber projektiert.

Dank euch im vorraus für euere Hilfe!!

AUF "Fehler"
O DBX 1.0 //Hilfsmerker Lampe
U(
ON DBX 0.1
O M 1.6
)
O DBX 0.6 //Lampentest
= DBX 0.0

= L 2.0 //Signalzustand Lampe
U DBX 0.1
= L 2.1 //Signalzustand Hupe
U DBX 0.6
= L 2.2 //Signalzustand Lampentest
U DBX 0.7
= L 2.3 //Signalzustand externe Quittung


AUF "Prog_Param"
L DBD 30 //Ausgang Lampe vorhanden ?
L DW#16#FFFFFFFF
==D //wenn ja dann ansteuern
SPB A002
U L 2.0
= A [DBD 30]

A002: L DBD 34 //Ausgang Hupe vorhanden ?
L DW#16#FFFFFFFF
==D //wenn ja dann ansteuern
SPB A003
U L 2.1
= A [DBD 34]

A003: L DBD 54 //Ausgang Lampentest vorhanden ?
L DW#16#FFFFFFFF
==D //wenn ja dann ansteuern
SPB A004
U L 2.2
= A [DBD 54]
 
Adressierung

Servus,

in diesem Programmausschnitt ist indirekte Adressierung verwendet. Das heißt, daß die Adresse des zu verarbeitenten Operanten in der Adresse in den eckigen Klammern steht.

z.B AUF DB10
U L 2.0
= A[DBD 30]

AUF DB10 // öffnet den Datenbaustein 10, dies ist auch möglich durch
... DB10.DBD30

L 2.0 // bezieht sich auf die Lokaldaten einer Funktion, diese haben für
einen Aufruf gültigkeit

=A [DBD30] // ist die indirekte Adressierung, die Adresse des
Ausganges steht im Datenbausteindoppelwort 30 des
gerade geöffneten DB. Und zwar in der Form

0000 0000 0000 0xxx xxxx xxxx xxxx x.yyy

dabei gibt das y die Bitadresse an und das x die
Byteadresse.

Hoffe das hilft.
Gruss Buh
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kannst du mir vielleicht anhand eines Programmes die indirekte Adressierung näher bringen?? z.B. mit einem Eingang E1.0 und der setzt den Ausgang A2.0

Ist für mich besser zum verstehen.
 
Ja das ist nicht leicht nachzuvollziehen.

L entspricht den Lokaldaten "temp" Leider wurde in dem Programmteil direkt eine Lokaladresse angesprochen, anstatt symbolisch. Das erschwert das lesen auch noch einmal.

Was hast Du denn mit dem Ausgang den du suchst vor?

Musst du überhaupt den Ursprung, die Zuweisung kennen oder genügt dir der Status?

pt
 
Adressierung

Das laden des Pointers erfolgt auf zwei Möglichkeiten,

AUF DB10
L 2#0000 0000 0000 0000 0000 0000 0000 1000 // entspricht Adresse 1.0
T DBD30
// oder mit
L P#1.0 // P gibt einen Pointer an, der bit codiert genau 3 Zeilen weiter oben steht auch das entspricht Adr. 1.0
T DBD30

L 2#0000 0000 0000 0000 0000 0000 0001 0011 //entspricht Adresse 2.3
// oder L P#2.3
T DBD34

// Das Programm sieht dann wie folgt aus
U E[DBD30] //U E1.0
=A [DBD34] //= A2.3


Die letzten 3 Bit entsprechen der Bitadresse also z.B. ...xxx.101 entspricht der Adresse x.5 .
Die Bits 19 bis 3 enthalten die Byteadr z.B. ..000 0000 0000 1000 1.101
das entspricht Adresse 17.5 .

Das gleiche Bitmuster wird auch mit dem Pointer erzeugt
L P#17.5 .

Es ist bei der Verwendung darauf zu achten, daß
- die Bitadresse nicht größer als 7 ist
- bei einer Byteadressierung (z.B. MB 10) die Bitadresse 0 ist
Beides führt zum Programmierfehler OB Aufruf.

Gruss Buh
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe noch was vergessen und zwar wenn du so adressierte Ausgänge suchst, ist zu beachten das diese vermutlich während der Laufzeit verändert werden. Sonst macht diese Adressierung wenig Sinn. Es ist also auf Transferoperationen in die jeweiligen Datenbausteinbereiche zu achten.

Gruss Buh
 
Hallo Buh,

das mit den letzten 3 Bits und die Byteadresse habe ich so weit verstanden.
Leider weiß ich jetzt immer noch nicht, wie z.B. der Ausgang 0.7 gesetzt wird bzw. wie das AB/AW0 in den DB geschrieben wird.
 
Adressierung

Wenn man einen Ausgang setzen möchte dann tut man das fast wie immer, nur das die Adresse des Ausganges eben in irgendeinem Bereich (DBD, MD) steht. Dieser ist in den eckigen Klammern angegeben.

...Bedingung
S A[DBD30] //Ausgang mit der jeweiligen Adresse [...] wird gesetzt

Hier ist mal ein kleines Beispiel. Als Register mit der Adresse wird das MD0 verwendet (geht mit DBD genau so). Mit E0.0 wird ein Zähler erhöht, dieser wird in die Bitadresse transferiert. Es wird noch ein Offset für die Byteadresse addiert und anschließend der gerade aktuelle Ausgang gesetzt. Im Ergebnis wandert der geschaltene Ausgang durch das AB2.

Code:
      L     0
      T     AB     2                    //Rücksetzen der Ausgänge
      U     E      0.0                  //erhöht Z1 um 1
      FP    M     10.0                 //Flankenmerker
      U     M     10.0
      ZV    Z      1                    //Zähler zählt die Adresse hoch
      L     Z      1
      L     8                             //Bitadresse max. 7
      >=I   
      R     Z      1
      L     Z      1
      L     16                           //Offset für Byteadresse
      +I    
      T     MD     0                  //Speicherbereich enthält Adresse
      SET                              //VKE=1
      S     A [MD 0]                //Setzen des Ausganges mit der Adresse MD0
      BE


Wenn du dir bei diesem Beispiel mal das MD0 und AB2 online ansiehst wird es dir bestimmt klar werden wie diese Adressierung funktioniert.

Gruss Buh
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Buh,

danke für dein Beispielprogramm. Jetzt hat es klick gemacht.
Das Programm habe ich ein klein wenig umgestrickt:

U E [DBD4]
SPBN a002
L 0
T AB 2

a002 :NOP 1

AUF DB 10
L P# 1.0
T DBD 0
L P# 1.1
T DBD 4



U E [DBD0]
SPBN A001

L DW#16#00000010
T DBD 8

S A [DBD8]
A001 :NOP 1

1) Welchen Vorteil hat es, das ich anstatt E1.0 und E1.1 die Pointeradressierung verwende?

2) Wenn ich einmal die Ausgangsadresse gesetzt habe, bleibt der Ausgang da, bis ich ihn wieder lösche. Warum ist das so?

3)d.h. wenn ich wie im oberen Beispiel DW#16#00000010 (17) lade, spreche ich den Ausgang A2.0 an. Wenn ich den Ausgang 10.0 ansprechen will, muß ich dementsprechend die Zahl im DW erhöhen.
Verstehe ich das richtig?

4) In dem Programm kommt auch noch folgendes vor:
Was ist ein FIFO (First in First out)?

5) Was bedeutet jetzt schon wieder dieser Befehl??
T DBB [AR1,P#54.0] Irgendwas mit Adressregister, oder?

AUF "Fehler"
LOOP: L DBW 10 //Wenn Zähler = 0
L DW#16#0 //dann neu "aufziehen"
>I
SPB L000
L DBW 6
T DBW 10

L DBW 12 //Hilfsmerker Lampe setzen
L 0 //Hilfszähler Lampe löschen
<>I
= DBX 1.0
T DBW 12
SPA ENW

L000: L DBW 10 //Adressregister berechnen
DEC 1
SLW 3
LAR1

U DBX 0.7
SPB QEIN
L DW#16#0
T DBB [AR1,P#34.0] //SPS-Quittungsbits löschen
SPA L001
QEIN: L DBB [AR1,P#14.0] //SPS-Quittungsbits für alle
INVI //Fehlermeldungen setzen, die auf
T DBB [AR1,P#34.0] //0 sind (Sammelquittung)
L 0
T DBB [AR1,P#74.0] //Verriegelungsbits löschen

L001: NOP 0
L DBB [AR1,P#94.0] //Temp =
L DBB [AR1,P#14.0] // Fehler UND (Fehler XOR Hilfsmerker)
T DBB [AR1,P#94.0]
XOW
L DBB [AR1,P#14.0]
UW
T DBB 4

L DBB [AR1,P#74.0] //Verriegelung =
OW //Verriegelung ODER Temp
T DBB [AR1,P#74.0]

L DBB 4 //Quittung =
INVI //Quittung UND KOMPLEMENT(TEMP)
L DBB [AR1,P#54.0]
UW
T DBB [AR1,P#54.0]

INVI
L DBB [AR1,P#74.0] //Verriegelung =
UW //(Verriegelung UND KOMPLEMENT(Quit))
L DBB [AR1,P#14.0] //ODER Fehler
OW
T DBB [AR1,P#74.0]

L 0
==I
SPB L002
L DBW 12 //Wenn Verriegelungsbit gesetzt
INC 1 //Hilfszähler Lampe hochzählen
T DBW 12

L002: L DBB 4 //Wenn Fehler dann Hupenflag setzen
L 0
<>I
S DBX 0.1

L DBW 10
DEC 1
T DBW 10

UN DBX 1.5
SPB LOOP
ENW: NOP 0

ich versuche das Programm ein wenig zu verstehen.
Es ist irgendwie kompliziert geschrieben.

Dank dir Buh für deine Hilfe!!!
 
Hallo INST,

zu 1.)

Mit Hilfe dieser Adressierung kann man die Adressen der jeweiligen Operantenbereiche während der Laufzeit des Programmes verändern.

zu 2.)

Das ist einfach so, da alles was gesetzt wird auch rückgesetzt werden muss. Es kann aber auch eine Zuweisung ( = ) verwendet werden, dann kann das Rücksetzen entfallen.

zu 3.)

Jawohl, das ist so richtig.

zu 4.)

Ein FIFO stellt einen Speicher dar, in dem die Daten nacheinander eingetragen werden. z.B. ein Schieberegister, dort werden die Daten die zuerst eingetragen werden auch als erstes ausgelesen. Solche Speicher werden z.B. für Stacks verwendet.

zu 5.)

Das ist ein Beispiel für die Registerindirekte Adressierung, bereichsintern. Hier wird das Adressregister 1 verwendet, dieses wird irgendwo vorher mit dem Befehl " LAR1 " geladen mit einer Adresse. Zu dieser Adresse wird dann noch der Pointer nach dem Komma addiert. Das heißt:

L 0
LAR1 // Lädt 0 in das Adressregister 1
L 100
T DBB[AR1,P#54.0] // Schreibt die 100 in das Datenbausteinbyte 54 da im AR1 0 steht.

--> Die Adresse ergibt sich aus AR1 + Pointer


Code:
L000: L DBW 10 //Adressregister berechnen 
DEC 1 
SLW 3 
LAR1 

U DBX 0.7 
SPB QEIN 
L DW#16#0 
T DBB [AR1,P#34.0] //SPS-Quittungsbits löschen

Hier wird die Registerindirekte Adressierung verwendet. Eine Adresse wird aus dem DBW10 geladen (Sie stellt eine Byteadresse dar, da Pointer auf Bits DW format haben müssen)
SLW 3 verschiebt den Inhalt des Akkus1 3 Stellen nach rechts. Das wird durchgeführt, da die Bitadresse 0 sein muß wenn andere Operanten als Bits verwendet werden.
LAR1 lädt die Adresse in das Adressregister.
T DBB[AR1,P#34.0] ist die Verwendung des Adressregisters


Gruss Buh
 
Hallo Buh,

danke für deine ausführliche Antworten und deine Mühe!! :!: :!:

Frage:

Folgendes Programm habe ich geschrieben zum Verständnis.

Auf DB10

L 4
LAR1

L 2
T DBB [AR1,P#12.0]

Laut deiner Aussage sollte als Ergebnis 6 im DB10,DBB12 stehen.
Wenn ich das ganze Online anschaue, dann steht im Adressregister 1 die 4 und im DBB12 steht die 2 drin.

Habe ich da irgendein Denkfehler???
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dein Denkfehler liegt darin, dass Du den "Byte.Bit" Format nicht berücksichtigt hast. Dein "4" setzt die Adresse Byte 0. Bit 4 in AR1. Um Byte 4 zu adressieren must Du zwischen L4 und LAR1 ein SLD 3 einsetzen, wie in Buh's Beispiel. (In diesem Fall tut's SLW 3 auch, aber Pointers sind DWORDs).

Dein zweiter Denkfehler ist, dass Du 6 in DBB12 erwartest. Die "4" was Du in LAR1 geschrieben hast (wenn Du es mit SLD 3 angepasst hast) wird mit Dein Offset P#12.0 addiert und zeigt nun auf DBB16. Hier wird die "2" was Du in AKKU1 geladen hast geschrieben. Die "4" die Du ursprunglich in AKKU1 geladen hast liegt nun in AKKU2 und Du hast die nicht mit AKKU1 addiert, deswegen wird 2 und nicht 6 in DBB16 (oder auch 12, ohne SLD 3) geschrieben.

Das ist nicht so klar wie ich's gern hätte, aber vielleicht reicht es! :?
 
Achso,
wenn der Profibus läuft, kann ich dann die PAWs(Bits) auch einfach erstmal über eine Variablentabelle Steuern. Bisher macht der MM4 nämlich keinen Mucks.
Auch mit dem DriveMonitor von Siemens habe ich nicht wirklich erfolg.
 
zu 4.)

Ein FIFO stellt einen Speicher dar, in dem die Daten nacheinander eingetragen werden. z.B. ein Schieberegister, dort werden die Daten die zuerst eingetragen werden auch als erstes ausgelesen. Solche Speicher werden z.B. für Stacks verwendet.

Für Stacks werden eigentlich LIFO 's verwendet (Last In First Out).

MfG Gast
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Read the manual

INST schrieb:
Hallo Buh,

danke für deine ausführliche Antworten und deine Mühe!! :!: :!:

Frage:

Folgendes Programm habe ich geschrieben zum Verständnis.

Auf DB10

L 4
LAR1

L 2
T DBB [AR1,P#12.0]

Laut deiner Aussage sollte als Ergebnis 6 im DB10,DBB12 stehen.
Wenn ich das ganze Online anschaue, dann steht im Adressregister 1 die 4 und im DBB12 steht die 2 drin.

Habe ich da irgendein Denkfehler???

In der Siemens Step7-Hilfe steht ein schönes Beispiel zu Pointern (Datei: s7bashda.chm unter Topic "Baustein zum Verändern des Pointers") und in der AWL-Hilfe existieren mind. drei Beispiele zur indirekten Adressierung. Einfach unter Index "Indirekte Adressierung" eingeben.

Darin sind diese beiden Themen ganz gut erklärt (inkl. Quellcode).
 
Zurück
Oben