marți, 30 octombrie 2012

Constante. Logica booleana. Masca

Valori Constante.

    Constantă vom numi un identificator (nume) asociat cu o valoare care nu poate fi modificată în timpul execuției programului. Utilizînd o constantă în locul unei şi aceleiași valori specificate în repetate rânduri, se va obține o simplificare a manipulării și menținerii programului. Mai mult decât atât, dând un nume explicit identificatorului de constantă, valorile definite ca constante vor da o claritate în elaborarea programului și o ușurință în menținerea lui.
    Utilizarea constantelor sporește nivelul de siguranță și reduce riscul de a introuce erori în program.
Dispare necesitatea de a ține minte valori concrete deoarece o denumire se memorizează mai bine. Erorile numelui  se verifică de obicei de compilator automat (în afara de cazurile în care se greșește cu un nume existent de constantă). Totodată introduce o ușurință de a introduce modificări în program, deoarece constanta este definită în program o singură dată, iar modificarea ei va afecta întreg programul în locurile în unde a fost utilizată.

Definirea constantelor

    Valorile constante se definesc o singură dată și iși păstrează valoarea pe întreg procesul de execuție a programului. În limbajul ASM pentru definirea valorilor constante vom avea două directive specializate:

  Directiva .EQU va defini un nume unei valori constante.

   .EQU SIZE = 10
   .EQU PIN7 = 7

  Directiva .DEF va defini un nume suplementar pentru un registru de uz general: 

   .DEF temp = R16

    De aici incolo temp poate fi utilizat ca operand în locul registrului R16, și orice modificre a lui temp va fi de fapt o modificare a lui R16.

Exemple: 

    ldi temp, SIZE  ; inarcarea constantei SIZE in registrul temp
    sbi PORTA, PIN7 ; setarea pinului 7 din portul A



Expresii constante
    
    Expresii constante vom numi expresiile la evaluarea căror participa în mod exlusiv doar numere constante iar rezultatul expresiei va fi la fel o constantă. Expresiile constante sunt evaluate în faza de precompilare.  Pentru formarea expresiilor constante putem folosi oricare expresii aritmetice și logice, cît și utilizarea maco-funcțiilor. În evaluarea expresiilor constante se va lua în considerație prioritatea operațiilor. 


exemple:
    .EQU A = 1023
    .EQU B = 1375
    .EQU C = (A+B)/2-17
    .EQU LOW_VAL = LOW(C)
    .EQU PIN7 = 7
    .EQU MASK = 1<<PIN7

Moduri de reprezentare a numerelor constante si conversii

    Numerele cu care suntem obisnuiți să le utilizăm sunt numere reprezentate în format zecimal, mai drept spus în baza 10. Acest format nu este unicul în care pot fi reprezentate numerele. Printre formatele de reprezentare a numerelor vom evidenția: binar, octal, zecimal, hexazecimal etc. 
Vom numi baza de enumeratie numărul de semne de disincție necesare scrierii unui număr. Orice număr poate fi reprezentat în oricare bază de numerație.
    Exemplu:
   
          28492(10)  = 67514(8)6F4C(16) = 0110111101001100(2)

   În programare, în afară de baza zecimală, cel mai frecvent utilizate sunt numerele binare și cele hexazecimle, în special pentru microcontrollere unde se operează la nivel jos al hardware-ului. 
    Pentru informații suplimentare despre baza de enumerație se poate consulta literatura aferentă, aici însă vom prezenta o metodă simplă de trecere dintr-o bază în alta și în special din cea hexazecimală în binară și invers.
    Fiecare cifră zecimală va reprezenta o tetradă în binar, și în așa mod conversia dintre aceste două sisteme se poate face utilizând tabelul de mai jos, în care se vor introduce toate cifrele hex și reprezentarea lor binară.

    DEC |  BIN | HEX 
     0  | 0000 |  0
     1  | 0001 |  1
     2  | 0010 |  2
     3  | 0011 |  3  
     4  | 0100 |  4
     5  | 0101 |  5
     6  | 0110 |  6
     7  | 0111 |  7  
     8  | 1000 |  8
     9  | 1001 |  9
    10  | 1010 |  A
    11  | 1011 |  B  
    12  | 1100 |  C
    13  | 1101 |  D
    14  | 1110 |  E
    15  | 1111 |  F  

    După cum vedem fiecărei tedrade binare i se asociază o cifră în hexazacimal. În așa mod un număr pe 16 biți va fi reprezentat de 2 octeți (8bit) adică 4 tetrade respectiv poate  fi reprezentat de 4 cifre hexazecimale.
  Exemplu:
        1001_0010__1010_1110(2)92AE(16)
          9    2      A    E
    Această conversie se poate efectua ușor dintr-o bază în alta, iar exersând se poate ajunge la un automatizm într-un timp scurt.
    O metodă simplificată de conversie a numerelor binare în decimale este de a memoriza șirul puterilor lui 2: 1, 2, 4, 8, 16, 32 etc. După care trecerea dintr-o bază în alta se reduce la suma acestor numere după principiul: adunăm dacă ordinul respectiv este "1"
  Exemplu:  
          11010101 = 213

1   1  0  1  0 1 0 1
128 64 32 16 8 4 2 1
128+64+ 0+16+0+4+0+1 = 213

Logica booleană.

    Luând în considerație ca Microcontrollerul operează cu date la nivel de valori logice "1" și "0" vom da niște noțiuni introductive în logica booleana și exemple de utilizare a lor în optimizarea elaborării programelor în limbajul ASM.
În logica booleană vom evidenția următorii operatori logici de bază : AND, OR,XOR, NOT.
Acești operatori au mai multe însemnări pentru fiecare din ele.

             AND  &  ∙  - Logic SI , intersectie
             OR   |  +  - Logic OR , reuniune
             XOR  ^  ⊕  - Logic Exclusiv OR
             NOT  ~  x' - Negatie

Vom prezenta mai jos tabela de adevăr pentru fiecare din ele:
        
       AND            OR             XOR        NOT
   |x1|x2|y |     |x1|x2|y |     |x1|x2|y |    ||y |
   |0 |0 |0 |     |0 |0 |0 |     |0 |0 |0 |    |0 |1 |
   |0 |1 |0 |     |0 |1 |1 |     |0 |1 |1 |    |1 |0 |
   |1 |0 |0 |     |1 |0 |1 |     |1 |0 |1 |
   |1 |1 |1 |     |1 |1 |1 |     |1 |1 |0 |

Operațiile logice pot avea și alte definiții ca de exemplu:
XOR - inversor comandat, comparator - resultat 1 dacă sunt diferite
AND - cheia electronică cu blocare pe zero (repetor comandat cu blocare pe zero).
OR    - cheia electronică cu blocare pe 1.

Mai multe detalii despre Logica booleană le puteți găsi aici

Operaţii cu masca.

    De multe ori avem nevoie sa modificăm anumiți biți dintr-o locație de memorie fie registru sau un periferic fără a atinge valorile celorlalți biți. În asemenea cazuri ne va veni în ajutor cunoștințele din logica booleană și un principiul de aplicare a unei măști la o valoare.
    De exemplu presupunem că vom avea nevoie să modificăm într-un număr aleator bitul 4 și 7 după cum urmează: setare, resetare sau inversare.

Aplicarea măștii de setare.

    Presupunem ca avem un numar pe 8 biți cu o valoare 0bxxxx_xxxx  și  vom dori să modificăm această valoare astfel încât să avem ca rezultat biții 4 și 7 în "1" adică 0b1xx1_xxxx   celelalte valori ale biților vor trebui sa rămână aceleași.
    Facînd o analiză a operațiilor logice (a tabelelor de adevăr) vom observa:

         x OR 0 = x  - nu modifica valoarea x
         x OR 1 = 1  - seteaza in 1 

    Deci am putea folosi această proprietate de a lăsa neschimbată valoare de intrare la operația OR cu 0 și de a seta în 1  în celalalt caz.
    Respectiv va trebui să formăm un numar pe 8 biți care ne-ar satisface condiția problemei, adică de a seta anumiți biți în "1" , biții 4 ș i 7.

     X X X X  X X X X 
OR   1 0 0 1  0 0 0 0  - mască de setare
     1 X X 1  X X X X 

  Vom numi Masca pentru setare o combinație de biți în care vom avea 1 în pozitiile pe care vream să le setăm. Operația de setare va fi realizată în baza operației OR a numărului cu masca. 

Aplicarea măștii de resetare.

Făcând aceeași analiză a operațiilor logice pentru a găsi o soluție pentru a reseta locațiile respective vom observa că:

     x AND 0 = 0  - reseteaza in 0
     x AND 1 = x  - nu modifica valoarea x


    Ca și în cazul precedent vom folosi această proprietate pentru a forma o mască de resetare

     X X X X  X X X X 
AND  0 1 1 0  1 1 1 1  - mască de resetare
     0 X X 0  X X X X 

 Masca de resetare vom numi o combinație de biți în care vom avea zerouri în pozițiile pe care vrem să le resetăm. Operația de resetare va fi realizată în baza operației AND a numărului cu masca.
   Pentru a avea aceeași mască resetare/setare, pentru setare aplicăm masca cu perația OR, pentru resetare aplicăm masca inversată cu operația AND.

       X X X X  X X X X 
AND  ~ 1 0 0 1  0 0 0 0  - mască setare inversata 
       1 X X 1  X X X X 

Inversarea cu masca.

    Pentru a inversa anumiți biți dintr-un număr vom aplica operatia XOR cu masca în care pozițiile de interes pentru inversare vor fi setate cu 1 iar celelalte respectiv cu zero. Ceia ce rezultă din urmatoarele.


     x XOR 0 =  x  - nu modifica valoarea x
     x XOR 1 = ~x  - inverseaza valoarea x

respectiv vom avea:

     X X X  X  X X X X 
XOR  1 0 0  1  0 0 0 0  - mască pentru inversare
    ~X X X ~X  X X X X 

Formarea măștilor


    Formare mastilor ar putea fi facută prin expresii constante. Stiind numărul de ordine al bitului care trebuie modificat, de exemplu al 4-lea,  am putea să-l reprezentăm prin expresia constantă 1 << 4 , adică unitatea deplasata cu 4 pozitii spre stânga.

  .EQU MASK = 1<<4  

    Pentru cazul în care vom avea format o mască cu mai mulți biți de interes, de ex 4,6,7, vom defini o expresie constantă  în baza sumei măștilor pentru fiecare bit de interes, adică:

  .EQU MASK = (1<<7)+(1<<6)+(1<<4)
      
     0 0 0 0  0 0 0 1
   + 1 0 0 0  0 0 0 0  
   + 0 1 0 0  0 0 0 0  
   + 0 0 0 1  0 0 0 0
     1 1 0 1  0 0 0 0 


    Același rezultat il vom avea dacă vom evalua exresia prin funcția OR al componentelor ce formează masca:

  .EQU MASK = (1<<7)|(1<<6)|(1<<4)
      
     0 0 0 0  0 0 0 1
  OR 1 0 0 0  0 0 0 0  
  OR 0 1 0 0  0 0 0 0  
  OR 0 0 0 1  0 0 0 0
     1 1 0 1  0 0 0 0 

    Lucrul cu măștile este utilizat de obicei la setarea sau resetarea unor biți dintr-un registru periferic. Fiecare bit în acest caz are un nume definit în fișierul antet pentru fiecare microcontroller în parte, sau am putea defini un nume în cadrul programului pentru acești biți, după care să utilizăm numele bitului pentru formarea măștilor:

  .EQU BITA = 7
  .EQU BITB = 4
  .EQU MASK = (1<<BITA)(1<<BITB)

  cbr R16, MASK