Zbirni jezik (assembler)
Zbirnik je programski jezik, ki ga lahko uvrstimo tik nad strojni jezik. Je jezik kratic, ki so ga uvedli programerji, da bi poenostavili uporabo strojnega jezika. Namesto da bi bili strojne kode strojnih ukazov prepisovali iz tabel, so ukaze poimenovali s kraticami, ki si jih je laže zapomniti kot številke. Zbirni jezik je predstavljen v razumljivejši obliki z mnemoniki ali smiselnimi okrajšavami. Zbirni jezik strojne ukaze oziroma instrukcije predstavlja v simbolični obliki in se ne more izvajati neposredno, saj ga je treba prej prevesti v strojni jezik.
Vsaka od 35 instrukcij mikrokontrolerja PIC16F628a ima v zbirnem jeziku svojo okrajšavo, ki jo imenujemo mnemonik. Zbirniški prevajalnik prevaja program, napisan v zbirnem jeziku po vrsticah tako, da mnemonike prevede v strojno kodo ukaza, ki jo razume centralna procesna enota mikrokontrolerja. Strojno kodo vpisuje v datoteko s končnico .hex, ki jo nato s programatorjem prenesemo v programski pomnilnik mikrokontrolerja.
Program v zbirnem programskem jeziku je sestavljen iz stolpca instrukcij, njihovih parametrov in komentarjev. Komentarji niso obvezni, vendar je program s komentarji preglednejši, saj nam ti opisujejo njegovo delovanje. V veliko pomoč so tudi pri odpravljanju napak.
Slika 1: Program v zbirnem jeziku
Labele ali naslove pišemo skrajno levo. Postavimo jih lahko kamor koli pred instrukcijo ali v novo vrstico med programom. Instrukcije ali ukaze pišemo s tabulatorsko tipko odmaknjene od levega roba, sledijo pa jim parametri. Če je parametrov več, jih moramo ločiti z vejicami. Komentarje lahko pišemo na konec katere koli vrstice ali v svojo vrstico, vedno pa jih moramo začeti s podpičjem.
Instrukcije mikrokontrolerja:
addlw k Add literal and work. Vrednost delovnega registra w prištej vrednosti konstante k. Rezultat shrani v delovni register. Instrukcija porabi 1 urin cikel.
addwf f Add work and file. Vrednosti registra f prištej vrednost delovnega registra w. Instrukcija porabi 1 urin cikel.
andlw k AND literal with work. Izvedi logično operacijo IN med delovnim registrom in konstantno vrednostjo k. Rezultat operacije shrani v delovni register. Instrukcija porabi 1 urin cikel.
andwf f AND work with file. Izvedi logično operacijo IN med vrednostjo delovnega registra in vrednostjo registra, zapisanega v parametru. Instrukcija porabi 1 urin cikel.
bcf f,n Bit clear file. V registru f postavi bit n na 0. Instrukcija porabi 1 urin cikel.
bsf f,n Bit set file. V registru f postavi bit n na 1. Instrukcija porabi 1 urin cikel.
btfss f,n Bit test file, skip if set. Testiraj bit n v registru f, preskoči naslednjo instrukcijo, če je 1. Instrukcija porabi 2 urina cikla pri preskoku naslednje instrukcije, če ne preskoči, pa enega.
btfsc f,n Bit test file, skip if clear. Testiraj bit n v registru f, preskoči naslednjo instrukcijo, če je 0. Instrukcija porabi 2 urina cikla pri preskoku naslednje instrukcije, če ne preskoči, pa enega.
call a Call sobroutine. Pokliči podprogram na naslovu a. Instrukcija porabi 2 urina cikla.
clrf f Clear file. V registru f postavi vse bite na vrednost 0. Instrukcija porabi 1 urin cikel.
clrw Clear work. V delovnem registru w postavi vse bite na vrednost 0. Instrukcija porabi 1 urin cikel.
clrwdt Clear watchdog timer. Vrednost časovnika stražnega mehanizma postavi na 0. Instrukcija porabi 1 urin cikel.
comf f Complement file. Negiraj vrednost registra f. Instrukcija porabi 1 urin cikel.
decf f Decrement file. Zmanjšaj vrednost registra f za 1. Instrukcija porabi 1 urin cikel.
decfsz f Decrement file, skip if zero. Zmanjšaj vrednost registra f za 1, preskoči naslednjo instrukcijo, če je vrednost registra f enaka 0. Instrukcija porabi 1 urin cikel, če pogoj ni izpolnjen, če je izpolnjen, pa 2 urina cikla.
goto a Unconditional branch. Nadaljuj izvajanje programa na naslovu a. Instrukcija porabi 2 urina cikla.
incf f Increment file. Povečaj vrednost registra f za 1. Instrukcija porabi 1 urin cikel.
incfsz f Increment file, skip if zero. Povečaj vrednost registra f za 1, preskoči naslednjo instrukcijo, če je vrednost registra f enaka 0. Instrukcija porabi 1 urin cikel, če pogoj ni izpolnjen, če je izpolnjen, pa 2 urina cikla.
iorlw k Inclusive OR literal with work. Izvedi logično operacijo ALI med delovnim registrom w in konstanto k. Rezultat operacije shrani v delovni register w. Instrukcija porabi 1 urin cikel.
iorwf f Inclusive OR work with file. Izvedi logično operacijo ALI med delovnim registrom w in registrom f. Instrukcija porabi 1 urin cikel.
movlw k Move literal to work. Vrednost konstante k prestavi v delovni register w. Instrukcija porabi 1 urin cikel.
movf f,d Move file. Vrednost registra f prestavi na mesto, določeno s parametrom d. Instrukcija porabi 1 urin cikel.
movwf f Move work to file. Podatek iz delovnega registra w prestavi v register f. Instrukcija porabi 1 urin cikel.
nop No operation. Ne naredi ničesar. Instrukcija porabi 1 urin cikel.
retfie Return from interrupt. Vrni se iz prekinitvenega podprograma. Instrukcija porabi 2 urina cikla.
rlf f Rotate left file through carry. Vsebino registra f rotiraj v levo skozi zastavico C. Instrukcija porabi 1 urin cikel.
return Return from sobroutine. Vrni se iz podprograma. Instrukcija porabi 2 urina cikla.
rrf f Rotate right file through carry. Vsebino registra f rotiraj v desno skozi zastavico C. Instrukcija porabi 1 urin cikel.
sleep Sleep. V časovnik stražnega mehanizma vpiši vrednost 0 in postavi mikrokontroler v režim delovanja sleep.
sublw k Subtract work from literal. Vrednost delovnega registra w odštej od številske konstante k. Rezultat shrani nazaj v delovni register w. Instrukcija porabi 1 urin cikel.
subwf f Subtract work from file. Vrednost delovnega registra odštej od vrednosti registra f. Instrukcija porabi 1 urin cikel.
swapf f Swap nibbles in file. Zamenjaj zgornji in spodnji polbajt v registru f. Instrukcija porabi 1 urin cikel.
xorlw k Exclusive OR literal with work. Izvedi ekskluzivno operacijo ALI med vrednostjo delovnega registra in konstanto k. Rezultat te operacije shrani v delovni register. Instrukcija porabi 1 urin cikel.
xorwf f Exclusive OR work with file. Izvedi ekskluzivno operacijo ALI med vrednostjo delovnega registra in vrednostjo registra f. Instrukcija porabi 1 urin cikel.
Direktive in konfiguracijski biti:
Direktive so ukazi v programu, ki se ne prevedejo v strojno kodo. Prevajalniku povejo, kako naj prevaja posamezne dele programa.
Direktiva list p=16f628a na začetku programa določi tip uporabljenega mikrokontrolerja, v našem primeru PIC16F628A.
Direktiva #include <p16f628a.inc> vključi v program datoteko p16f628a.inc, ki vsebuje imena registrov v mikrokontrolerju.
Direktiva org določi naslov programskega pomnilnika, kamor se bo vpisoval program. Naslov je podan kot parameter tej direktivi.
Z direktivo end zaključimo program.
S konfiguracijskimi biti lahko izbiramo med zunanjim in notranjim oscilatorjem, vrsto oscilatorja, vlogo ponastavitvenega vezja (reset vezja), stabilizacijo oscilatorja pred izvajanjem programa, ko mikrokontroler priključimo na napajalno napetost, vključimo oziroma izključimo časovnik stražnega mehanizma (Watchdog timer), zaščitimo program pred kopiranjem, določimo pa lahko še nekatere druge parametre, ki jih v naših vajah ne bomo uporabljali. Vsi parametri so za posamezne tipe mikrokontrolerjev opisani v karakterističnih podatkih proizvajalca Microchipa.
Konfiguracijske bite nastavimo z določitvijo vrednosti posameznih bitov v registru CONFIG. Do tega registra, njegov specialni naslov v podatkovnem pomnilniku je 2007h, lahko dostopamo le med programiranjem.
Register CONFIG (RAM naslov: 2007h)
Tabela 1: Register CONFIG
Nastavitev konfiguracijskih bitov za vaje:
Bit 0 (FOSC0), bit 1 (FOSC1) in bit 4 (FOSC2) določajo izbiro oscilatorja. Na mikrokontroler bomo priključili kristalni oscilator s frekvenco 4 MHz. Priključili ga bomo med pin 15 (RA6/OSC2/CLKOUT) in pin 16 (RA7/OSC1/CLKIN). Za takšno izbiro določimo vrednost teh treh bitov: bit 0 = 1, bit 1 = 0 in bit 4 = 0.
Bit 2 (WDTE) določa delovanje stražnega mehanizma. Vlogo tega časovnika bomo spoznali v nadaljevanju. Pri vajah bomo izklopili delovanje tega časovnika, zato bo vrednost bita 2 = 0.
Bit 3 (/PWRTE) določa vklop ali izklop stabilizacije kristalnega oscilatorja, preden začne mikrokontroler izvajati program. Če je stabilizacija vklopljena, ta traja 72 ms. Mi bomo stabilizacijo omogočili, zato bo vrednost bita 3 = 1.
Bit 5 (MCLRE) določa vlogo ponastavitvenega vezja, priključenega na pin 4 (RA5//MCLR/Vpp) mikrokontrolerja. Če je vrednost bita 5 = 1, omogočimo delovanje ponastavitvenega (reset) vezja. V tem primeru mikrokontroler izvaja program, ko je na njegovem pinu 4 napetost +5 V (nivo logične 1). Mikrokontroler ponastavimo, če ta pin povežemo z maso (nivo logične 0). Po ponastavitvi se prične program izvajati na naslovu 000h podatkovnega pomnilnika. Če je vrednost bita 4 = 0, onemogočimo delovanje ponastavitvenega vezja, hkrati pa določimo pin RA5 kot vhodni pin mikrokontrolerja.
Bit 6 (BOREN) omogoča delovanje posebnega vezja v mikrokontrolerju, ki poskrbi za ponastavitev programa, če napetost VDD za daljši čas (72 ms) pade pod določen napetostni nivo. Tega delovanja ne bomo omogočili, zato bo vrednost bita 6 = 0.
Bit 7 (LVP) omogoča nizko napetostno programiranje, ki se v tem tipu mikrokontrolerja ne uporablja. Če je vrednost bita 7 = 0, lahko uporabimo pin RB4 kot vhodni ali kot izhodni pin mikrokontrolerja.
Bit 8 (/CPD) omogoča zaščito programskega pomnilnika pred kopiranjem, če je njegova vrednost enaka 0. Programskega pomnilnika ne bomo zaščitili pred kopiranjem, zato bo vrednost bita 8 = 1.
Bit 13 (/CP) omogoča zaščito programa v pomnilniku Flash (od naslova 0000h do 07FFh) pred kopiranjem, če je njegova vrednost enaka 0. Programske kode v pomnilniku Flash ne bomo zaščitili, zato bo vrednost bita 13 = 1.
Biti od 9 do 12 v mikrokontrolerju PIC16F628A niso podprti in se berejo kot 0.
Konfiguracijske bite lahko določimo na začetku programa, takoj za direktivo #include na dva načina. Prvi način opisuje imena konfiguracijskih bitov in njihovo stanje, drugi način pa vrednosti vseh konfiguracijskih bitov, najpogosteje zapisanih v heksadecimalnem številskem sistemu. Ker že poznamo direktive, zapišimo prve tri vrstice programa:
list p=16f628a ;Tip mikrokontrolerja.
#include <p16f628a.inc> ;Vključi v program datoteko p16f628a.inc, ki vsebuje imena registrov v mikrokontrolerju.
__CONFIG _CP_OFF &_WDT_OFF &_PWRTE_ON &_MCLRE_ON &_LVP_OFF &_XT_OSC
Konfiguracijski biti določajo izklop zaščite pred kopiranjem, izklop stražnega mehanizma, vklop stabilizacije oscilatorja, omogočena sta ponastavljanje in uporaba pina RB4 ter uporaba zunanjega kristalnega oscilatorja.
Za opisane nastavitve je vrednost registra CONFIG zapisana v binarni obliki:
__CONFIG b'10000100101001'
Zapišimo še vrednost registra CONFIG v heksadecimalnem zapisu:
__CONFIG 0x2129
Določitev vhodno-izhodnih pinov mikrokontrolerja:
Mikrokontrolerju PIC16f628a določimo nekatere pine kot vhodne in nekatere kot izhodne zaradi vezja, s katerim deluje. Glavna naloga mikrokontrolerja je namreč ta, da na posamezne pine pošilja napetost +5 V (1) ali napetost 0 V (0) in preverja, ali je na določenih pinih napetost +5 V (1) ali je ni (0). V odvisnosti od vezja, s katerim bo deloval, določimo ustrezne pine kot vhodne oziroma kot izhodne.
Slika 2: Določitev vhodno-izhodnih pinov mikrokontrolerja
Mikrokontroler PIC16f628a ima 16 vhodno-izhodnih pinov, ki so razdeljeni na port A in port B. Programsko so pini združeni v register PORTA in register PORTB. Smer vsakega pina (ali bo deloval kot vhodni ali kot izhodni pin) določimo z vrednostjo bitov v registru TRISA za PORTA in v registru TRISB za PORTB. Če ima določen pin v registru TRIS vrednost 0, bo deloval kot izhodni pin, če pa ima vrednost 1, bo deloval kot vhodni pin. Na sliki 2 vidimo, da so pini RA0, RA2, RA4, RA5, RB0, RB1, RB2 in RB7 določeni kot vhodni pini, drugi pa kot izhodni pini.
Od vseh 16 pinov mikrokontrolerja PIC16f628a imajo nekateri posebno vlogo:
Pine RA0, RA1, RA2 in RA3 lahko uporabimo kot vhode analognih komparatorjev, pina RA3 in RA4 sta v tem primeru izhoda komparatorjev. Lahko pa pine RA0–RA3 uporabimo kot digitalne vhode oziroma izhode. Izbiro nastavimo z določitvijo vrednosti bitov registra CMCON (Comparator control register).
Pin RA5 lahko uporabimo le kot digitalni vhod ali pa kot ponastavitvni (reset) vhod. V tem primeru nam služi za ponastavitev mikrokontrolerja (resetiranje mikrokontrolerja).
Pin RA4 lahko ob ustrezni nastavitvi mikrokontrolerja uporabimo kot števni vhod časovnika TMR0. V tem primeru deluje TMR0 kot števec impulzov.
Na pina RA6 in RA7 priključimo zunanji kristalni oscilator, ki mikrokontrolerju določa takt, s katerim ta izvršuje instrukcije. Če pa uporabljamo notranji oscilator, lahko ta dva pina uporabljamo kot digitalna vhoda oziroma izhoda.
Pin RB0 nam lahko ob pravilni nastavitvi mikrokontrolerja proži prekinitve vsakič, ko se na njem pojavi ustrezna sprememba signala. Prekinitve nam lahko prožijo tudi ustrezne spremembe signala na pinih RB4, RB5, RB6 in RB7.
Pin RB3 lahko uporabimo tudi kot vhod oziroma izhod pulzno širinsko moduliranega signala (PWM).
Program za določitev vhodno-izhodnih pinov, kot je prikazano na sliki 2 je:
list p=16f628a ;Tip mikrokontrolerja.
#include <p16f628a.inc> ;Vključi v program datoteko p16f628a.inc.
__CONFIG 0x2129 ;Konfiguracijski biti.
org 0x000 ;Reset vektor.
goto Glavni ;Nadaljuj izvajanje programa na naslovu Glavni.
org 0x004 ;Prekinitveni vektor.
Glavni
bcf STATUS,5 ;Banka 0
movlw b'00000111'
movwf CMCON ;Prve tri bite registra CMCON postavimo na 1 => Onemogočimo komparatorje na PORTA.
bsf STATUS,5 ;Banka 1 (peti bit registra STATUS postavimo na 1).
movlw b'00110101'
movwf TRISA ;Pini RA0, RA2, RA4 in RA5 so vhodni, drugi so izhodni.
movlw b'10000111'
movwf TRISB ;Pini RB0, RB1, RB2 in RB7 so vhodni, drugi so izhodni.
bcf STATUS,5
clrf PORTB ;Inicializacija PORTB (register PORTB je v banki 0).
end