plc_tippser
Level-1
- Beiträge
- 2.493
- Reaktionspunkte
- 315
-> Hier kostenlos registrieren
von Volker
pointer
Hier ein paar Beispiele zur indirekten Adressierung / Pointer
Ein Merkerwort laden indem wir den Pointer direkt laden.
Dies ist unflexibel.
-----------------------------------
Eleganter geht es, indem wir den Pointer selbst erzeugen und über das Adressregister ansprechen.
Schon besser. Aber warum schieben wir 3 nach links?
Das liegt am Aufbau des Pointer. vereinfacht: Byteadress(16Bit).Bitadress(3Bit). (genauerers im Bild im Anhang)
Die 30 liegt also durch das schieben in der Byteadresse. die Bitadresse ist 0.
-----------------------------------
Nun gibt es noch den Versatz (p#0.0). Dieser wird zum Pointer im Adressregister hinzuaddiert.
Fast perfekt.
-----------------------------------
Nun wollen wir auch noch die Bitadresse fexibel gestalten.
-----------------------------------
Um indirekt auf ein Datenwort zugreifen zu können, ist es zwingend erforderlich den Datenbaustein vorher zu öffnen.
-----------------------------------
Anwendungsbeispiel mit einer Schleife
einige Bauteine für weitere variablen / blöcke findet ihr auf der homepage von volker.
-----------------------------------
Indirekt auf einen Bereich im Temp-Bereich zugreifen
nummer: typ int im temp-bereich an adresse 0
maschine: Array [0..5] of int im temp-bereich ab adresse 2
-----------------------------------
Es kann auch Adressregister2 (AR2) verwendet werden.
Aber Vorsicht:
Das DI-Register und das Adressregister AR2 werden systemseitig für den FB- und Multiinstanz-CALL verwendet. Bei FC's braucht ihr euch nicht darum zu kümmern.
Weiterführende Themen: Any-Zeiger für Datentypen
.


Hier ein paar Beispiele zur indirekten Adressierung / Pointer
Ein Merkerwort laden indem wir den Pointer direkt laden.
Code:
L P#30.0
T MD 10
L MW [MD 10] // lädt das mw30
-----------------------------------
Eleganter geht es, indem wir den Pointer selbst erzeugen und über das Adressregister ansprechen.
Code:
L 30
SLD 3
LAR1 // ergibt einen pointer von P#30.0 in adressregister1
L MW [AR1,P#0.0] // lädt das mw30
Das liegt am Aufbau des Pointer. vereinfacht: Byteadress(16Bit).Bitadress(3Bit). (genauerers im Bild im Anhang)
Die 30 liegt also durch das schieben in der Byteadresse. die Bitadresse ist 0.
-----------------------------------
Nun gibt es noch den Versatz (p#0.0). Dieser wird zum Pointer im Adressregister hinzuaddiert.
Code:
L MW [AR1,P#2.0] // lädt das mw32 (30 + 2.0)
U M [AR1,P#4.4] // fragt M 34.4 ab
-----------------------------------
Nun wollen wir auch noch die Bitadresse fexibel gestalten.
Code:
L 30
SLD 3
LAR1 // im ar1 steht p#30.0
L 4
+AR1 // die 4 wird zum ar1 hinzuaddiert. im ar1 steht jetzt p#30.4
U E [AR1,P#0.0] // fragt e30.4 ab
L EW [AR1,P#0.0] [COLOR=red]// das würde die cpu in stop bringen, da es das ew30.4 nicht gibt.[/COLOR]
[COLOR=red] // nur bei bitoperationen darf die bitadresse <>0 sein.[/COLOR]
Um indirekt auf ein Datenwort zugreifen zu können, ist es zwingend erforderlich den Datenbaustein vorher zu öffnen.
Code:
[COLOR=red]L db10.dbw [AR1,P#0.0] // dies funktioniert nicht[/COLOR]
AUF DB 10
L DBW [AR1,P#0.0] // so ist es richtig
Anwendungsbeispiel mit einer Schleife
Code:
FILO für Datenbyte (FirstInLastOut)
FiLo __\ byte1 \________________
| / / |
| byte2 \_________ /__|3.
| / | \
| byte3 \__ /__|2.
| / | \
| byte4 /__|1.
| \
|
|
quelle 4.|__/ byte
\
Ablauf:
1. zielbyte 3 wird nach zielbyte 4 kopiert. das alte byte 4 geht verloren.
2. zielbyte 2 wird nach zielbyte 3 kopiert
3. zielbyte 1 wird nach zielbyte 2 kopiert
4. quellbyte 1 wird nach zielbyte 1 kopiert
Code:
AUF #Datenbaustein //Typ: Block_DB
L #Datenende //Typ: INT
L 1
-I
T #index //Typ: DINT
anf: NOP 0 //Schleifenanfang
L #index
SLD 3 //pointer erzeugen
LAR1 //in das Adressregister laden
L DBB [AR1,P#0.0]
T DBB [AR1,P#1.0]
L #index
L 1
-I //Index um 1 verringern
T #index
L 1
+I
L #Datenanfang //Typ: INT
<=I //prüfen ob fertig
SPB ende //wenn ja ende
SPA anf //sonst schleife wiederholen
ende: NOP 0
L #Eintrag //Typ: BYTE
T DBB [AR1,P#0.0] //neues byte eintragen
-----------------------------------
Indirekt auf einen Bereich im Temp-Bereich zugreifen
nummer: typ int im temp-bereich an adresse 0
maschine: Array [0..5] of int im temp-bereich ab adresse 2
Code:
// var zum test vorbelegen
L 2
T #nummer
//----------------
L P##maschine //pointer auf array laden
LAR1 //ins adressregister speichern
L #nummer
L 2
*I //mit 2 multiplizieren da typ:int
SLD 3 //pointer bauen
+AR1 //zum adressregister hinzuaddieren
L W [AR1,P#0.0] //läd den wert von #maschine[2]
Es kann auch Adressregister2 (AR2) verwendet werden.
Aber Vorsicht:
Das DI-Register und das Adressregister AR2 werden systemseitig für den FB- und Multiinstanz-CALL verwendet. Bei FC's braucht ihr euch nicht darum zu kümmern.
Weiterführende Themen: Any-Zeiger für Datentypen
.
Anhänge
Zuletzt bearbeitet von einem Moderator: