4-ről 16-ra dekódoló blokk

Mi ez a dekóder?
Olyan program blokk, amelyik egy egész típusú (INT) bemenettel rendelkezik és 16 logikai típusú (BOOL) kimenete van. A bementen érkező érték kiválaszt egy kimenetet, amit logikai 1 állapotba kapcsol (TRUE), a többi logikai 0 (FALSE) marad.
A bemeneten 0-15 tartományba eső szám érkezik, ami a 0-15 számú kimenet kiválasztását végzi. Pl. ha a 4 jön a bemenetre, akkor a 4-es kimenet lesz logikai 1, ha 9 érkezik, akkor a 9-es kimenet lesz logikai 1 és így tovább.
Egy választókapcsolóhoz is hasonlíthatjuk, amelyiknek 16 állása van és a mozgó érintkezőjére logikai 1 állapot van "kötve". A kapcsoló 16 fix érintkezője a 16 kimenet, melyek közül az egyikre rákapcsolja a logikai 1 állapotot. A blokk bemenetére küldött szám a kapcsoló adott számú állásba való elfordításának felel meg.
A különbség annyi,  hogy ha 0-nál kisebb, vagy 15-nél nagyobb szám kerül a blokk bemenetére, akkor az összes kimenet 0 állapotú lesz.
 
Mire jó?
Előfordul, hogy egy egész számot kell ilyen módon "binárissá" konvertálni. A leggyakoribb felhasználása valamilyen kiválasztás megvalósítása.
Pl. HMI-n egy szimbolikus I/O mezőt helyezünk el. Az I/O mezőhöz rendelt változó értékeihez text list segítségével szövegeket rendelünk hozzá.  Ebből a  felhasználó választhat egyet, mire a változóba kerül a kiválasztott elem száma. Ha ezt a változót adjuk át a dekódoló blokknak, akkor az "szétszedi" a választási lehetőségeket egy bites információkra. Ezzel a blokkal maximum 16 választási lehetőséget tudunk használni.

De léteznek ún. BCD kapcsolók is. Ez egy több állású kapcsoló amelynek nem tartozik minden állásához egy külön kivezetés, hanem bináris BCD kódot ad. Egy ilyen kapcsolóval csökkenthető egy berendezés kézi működtetéséhez szükséges kezelőszervek száma. A kezelő a kapcsolóval kiválasztja hogy a gép mely részét kívánja mozgatni, majd megnyomja a mozgatásra szolgáló gombot. Az ilyen kapcsoló által szolgáltatott BCD kód dekódolására is alkalmas ez a blokk.

Nem utolsó sorban pedig alkalmas arra is, hogy bemutassam vele az indirekt címzés egy egyszerű módját és azt, hogyan oldható meg ugyanaz a feladat merőben eltérő módon.

1. változat: összehasonlítás
Programozás szempontjából a legegyszerűbb megoldás a blokk megvalósítására, ha annyi összehasonlító utasítást helyezünk el benne, amennyi kimenete van. Ha a #SELECT kiváklasztó bemenet bemeneten 0 van, akkor bekapcsolja az #S0 kimenetet. Ha #SELECT 1, akkor az #S1 kimenetet, és így tovább.
Ez összesen 16 összehasonlító utasítást jelent.




A többi összehasonlító műveletet nem tettem ide. A sort további 13 követi a fentivel megegyező minta alapján.
Ez a megoldás nem túl praktikus, de működik. A program sokkal nagyobb és lassabb a szükségesnél.
A blokk hívása már áttekinthetőbb valamivel:


2. változat, indirekt címzés, bináris kimenetek
Ez a példa merőben eltérő megoldást mutat be.
A lényege a következő: Beolvassa a #SELECT kiválasztó bemenet értékét egy cím regiszterbe. 1-be állítja az RLO bitet (Result of Logic Operation) majd megcímez egy memóriaterületeten egy bitet. Mégpedig a #SELECT tartalmával azonos című bitet, majd beleteszi az RLO-t (tehát az 1-et).
A megvalósításhoz indirekt címzés szükséges, amit az AR1 címregiszter használatával van megoldva STL nyelven. A dekóder funkció FC blokkba került. Emiatt szükség van egy kis körítésre, mert az FC be és kimeneti változói nem címezhetők meg közvetlenül.
Ezért az indirekt címzéssel először egy belső lokális változó tartalmát állítja be, majd ezt bitenként átmásolja a blokk kimeneti változójába.
A blokk a #SELECT bemeneten érkező értékből számolja ki annak a bitnek a címét a lokális változó területen (L area) amelyiket 1-be kell billenteni, ezért védelemre is szükség van. A védelem arra szolgál, hogy ha a #SELECT bemeneten 15-nél nagyobb vagy 0-nál kisebb értéket tartalmaz, akkor ne számoljon belőle címet, mert az hibához vezethet (tartományom kívüli címzés, ami alap esetben CPU stop állapotot eredményen).






A 15 network-ből álló első változathoz képest sokkal tömörebb, bár a NW2-ben lévő másolgatás elég csúnya megoldás.
Ennek a másolgatásnak az a célja, hogy a word típusúként deklarált #OUT_TMP változó 16 bitjét közvetlen címzéssel átmásolja a blokk kimenetére (#S0-#S15-re).
A blokk hívása teljesen megegyezik az 1-es példában látottal, mert ennek a blokknak ugyanolyan be és kimeneti paraméterei vannak mint annak:


3. változat, word kimenet
Ha nem akarjuk hogy a blokkunk ennyire "szőrös" legyen, vagyis csökkenteni szeretnénk a paraméterek (be és kimenetek) számát, akkor használhatunk WORD típusú kimenetet is.





A blokk hívása:


Na ez már nem olyan nagy és szőrös. A kevésbé gyakorlottak számára nem annyira érthető, mint az előző két blokk hívása. A másik következmény, hogy mindenképpen elhasznál 16 bitet. Akkor is, ha nem akarjuk mind a 16 bitet kihasználni, mert mondjuk 9 választási lehetőséget kell kezelni.
A bitenként kivezetett blokk nem használt kimeneteire megadhatunk egy "dummy" lokális változót, amit nem használunk fel. Itt azonban mindig írni fogja mind a 16 bitet.
Az eredményt egy 16 bites word-ben kapjuk, de természetesen bitenként is felhasználhatjuk a tartalmát. Pl. úgy, ahogy a példán is látható, merker word-öt adunk meg paraméterként (MW100) és azt bitenként címezzük.
A címregiszteres címzés miatt a fordított byte sorrendű tárolás nem cseréli fel a bitek sorrendjét mint ahogy azt várnánk. 0 értéket tartalmazó #SELECT-hez az M100.0, 1-hez az M100.1, 7-hez az M100.7, 8-hoz az M101.0, 15-höz az M101.7 bit tartozik.

4. változat, FB blokk
Megússzuk az átmeneti változók használatát és a bináris kimenetekre történő utólagos másolást, ha FB blokkot használunk.
Mivel az FB a ki és bemeneti változóit egy DB-ben tartja, meg lehet őket címezni a blokkból.





Az indexelt címzésnél azért kerül P#2.0 az utasításba a korábbi P#0.0 helyett, mert itt a kimeneti bitek a 2-es címen vannak, ezért a címzésnél 2 byte-nyi ofszetet kell használni. Ez látható is a blokk interfész részében:



Ha nem akarjuk kihasználni mind a 16 választási lehetőséget, a nem használt kimeneteket egyszerűen szabaon lehet hagyni. FB blokknél ez megengedett (FC-nél nem):



Kapcsolódó írások:
Az ANY paramétertípus
Az S7 PLC programozása
S7 300/400 indirekt címzés, pointerek


Szirty