DB-k címzése

Az S7300-400 adatterületek c. írásban említést nyert, hogy adatblokkok (DB-k) adatait abszolút címzés használatakor címezhetjük a teljes cím kiírásával, Pl. DB2.DBW4, vagy a blokk OPN utasítással történő megnyitása után a DB-n belüli címmel, pl. DBW4.
Amikor a programban egymás után sok címet kell beírni, ami ugyanazon DB-n belülre mutat, hasznos dolog.

Van azonban a dolognak egy olyan sajátossága, amit ha nem ismerünk, könnyen vétünk olyan hibát, amit nehezen találunk meg. Ez az írás ezzel a sajátossággal foglalkozik.
Hogy a dolog teljes legyen, lássunk egy egyszerű példát arra, miről is van szó:



A fenti példában A DB1-es blokk különböző címeire értékeket tölt fel. Minden Transfer megkapja a teljes címet, a DB számával együtt..
A "spórolós" módszer szerint a fenti kód az alábbiak szerint módosul:


OPN DB 1 utasítással "megnyitottuk a DB1-es adatblokkot. Azt gondolnánk, hogy innentől a rövid címmel megadott címek (ahol nem szerepel a DB száma, csak a belső cím) A DB1-re fognak hivatkozni. Ez ebben a formában nem igaz minden esetben. A fenti esetben igaz, a fenti két programrészlet azonos eredménnyel fut le..

Hogy érthető legyen mikor nem és akkor miért nem, ahhoz meg kell ismernünk a dolog mechanizmusát.
Az S7 két darab DB regiszterrel dolgozik (DB register 1 és DB register 2). A DB regiszterek segítik a DB-k címzését úgy, hogy amikor egy shared DB-t címzünk, akkor a címzendő DB száma a DB register1-be kerül és a címzés arra a DB-re fog vonatkozni, amelyik DB száma a DB regiszterben van. (Ha instance DB-t címzünk, annak száma a DB register2-be kerül).
A DB regiszter akkor kap értéket, amikor teljes címmel címzünk vagy amikor az OPN utasítással "megnyitunk" egy DB-t.Utána a címzés mindig a DB regiszter tartalma alapján történik. Amikor nem teljes címet adunk meg, akkor a DB regiszter értéke nem változik.

Mindebből az következik, hogy az OPN utasítás végrehajtása után kiadott, más DB-re vonatkozó teljes címmel történő címzést követő rövid cím már nem az OPN-el megnyitott blokkra, hanem a teljes címmel hivatkozott blokkra fog vonatkozni, mivel a teljes cím felülírta (módosította a DB regiszter tartalmát).

Lássunk erre is egy példát:



Az OPN DB 1 a DB regiszterbe 1-et tölt, így az ezt követő két rövid címmel szereplő Transfer a DB 1-et fogja használni.A teljes címmel adott T DB6.DBW 0 utasítás végrehajtásakor azonban a DB regiszterbe 6 kerül.
Ezért a kékkel keretezett ismét rövid címmel szereplő utasítások már a DB6-ban akarnak címezni.
Ha ezt a programot lefuttatjuk, monitorozzuk és beállítjuk az 1-es DB regiszter tartalmának a kiírását, nyomon is tudjuk követni.a dolgot:



Látható, hogy a DB1 (1-es DB regiszter) tartalma 6 lesz a kék vonal alatt.
Ha használunk rövid címeket, akkor erre nagyon oda kell figyelni, mert csúnya kalamajkát okozhat ha pár utasítás teljesen más DB blokkba kezd el nyúlkálni (főleg írni). Szerencsésebb esetben a nem kívánt blokk elérés hibára is futhat ha az a blokk kisebb és a mutatott cím a DB-n kívülre címez.
Ilyenkor kapunk egy Area length error-t és ha ezt nem kezeli egy OB, akkor a CPU leáll.
Természetesen mindegy hogy a program STL, LAD vagy FBD, a fentiek mindegyikre vonatkoznak, hiszen rövidített címek használata lehetséges mindhárom nyelvben és OPN utasítás is van.

Tapasztalataim alapján ilyen hibát akkor könnyű véteni, amikor hosszú sorokon keresztül minden DB cím rövid (főleg ha az egész blokk és csak az elején van egy OPN) majd ebben programot módosítunk úgy, hogy beillesztünk pár új sort, amiben teljes címmel más DB-ket kezelünk.
Ha elkerülhetetlen, hogy más DB-be nyúljunk, a rövid címeket tartalmazó sorok erdejében, akkor az alábbi lehetőségeink vannak:
Gond lehet, ha az OPN-el megnyitott blokk száma nem konstans (fix) hanem a program számítja ki futás közben valamiből és az első OPN után ez az információ a blokk belsejében már nem áll rendelkezésre.Lokális változó használatával ezt is áthidalhatjuk.

Látható, hogy a rövid címek használatának van hátránya is.
További hátrány, hogy a program áttekinthetősége, érthetősége is romlik miatta, valamint a rövid címeket használó programokban nehezebb megtalálni azt az utasítást amelyik egy bizonyos DB egy bizonyos címére ír vagy onnan olvas.

Például egy hibakeresés során tudni szeretnénk hol írja a program a DB1.DBD0 címet, akkor a kereszt referencia és a Go To Location nem fog tudni segíteni, mert a DB1.DBD0 címre nincs közvetlen hivatkozás, csak a DBD0-ra, ami viszont nem feltétlenül DB1...



A Go To Location funkciót asználhatjuk rövid cím keresésére is. Azzal azonban minden olyan címzést meg fog találni, ami DBD0-ra hivatkozik, nem csak azt amelyik DB1.DBD0-ra. Ilyenkor egyenként át kell nézni melyik előtt milyen blokkra vonatkozó OPN vagy teljes címhivatkozás van.
Ha a program nagy, sok DB-vel és történetesen a DBD0 címet sok helyen használja más DB-ben is, akkor ez nehezíti a keresést:



Ilyen rövid cím kereséskor a teljes című találatokat is mutatja. Szerencsére ha a kurzor egy teljes című hivatkozáson áll, akkor a lista tetején kijelzi melyik DB-re vonatkozik (rövid címnél itt DB? jelenik meg) így nem kell feltétlen minden találatot személyesen ellenőrizni, mert itt látható ha a keresett cím biztos nem oda mutat mint amit keresünk.

Szó volt arról, hogy két DB regiszter van. A shared DB-k címzésével (megnyitásával) a DB1 regiszter foglalkozik, a DB2 regiszter pedig az instance DB-k címzésével. Így egyszerre két DB-re hivatkozhatunk rövid címekkel. Egy shared és egy instance DB-re. Nincs arra szabály, hogy a shared-ként megnyitott DB valóban shared, az instance DB-ként megnyitott valóban instance DB legyen. Ezért kezelhetünk rövid címekkel egyszerre két shared DB-t is:



A zölddel kiemelt sorok a DB1-et címzik az 1-es DB regiszter tartalma alapján (shared), a kékkel kiemelt sorok a DB3-at címzik a 2-es DB regiszter tartalma alapján (instance).

Megjegyzés:
Indirekt címzést csak rövid címekkel lehet művelni.
Ha szimbolikus címzést használunk, akkor csak teljes címeket használhatunk:




2012. nov. 2
Szirty