Laboratorijske vaje pri Integralnih proizvodnih sistemih. Boštjan Murovec

Σχετικά έγγραφα
Diferencialna enačba, v kateri nastopata neznana funkcija in njen odvod v prvi potenci

Zaporedja. Matematika 1. Gregor Dolinar. Fakulteta za elektrotehniko Univerza v Ljubljani. 22. oktober Gregor Dolinar Matematika 1

Funkcijske vrste. Matematika 2. Gregor Dolinar. Fakulteta za elektrotehniko Univerza v Ljubljani. 2. april Gregor Dolinar Matematika 2

Odvod. Matematika 1. Gregor Dolinar. Fakulteta za elektrotehniko Univerza v Ljubljani. 10. december Gregor Dolinar Matematika 1

Tretja vaja iz matematike 1

Odvod. Matematika 1. Gregor Dolinar. Fakulteta za elektrotehniko Univerza v Ljubljani. 5. december Gregor Dolinar Matematika 1

KODE ZA ODKRIVANJE IN ODPRAVLJANJE NAPAK

MATEMATIČNI IZRAZI V MAFIRA WIKIJU

Funkcije. Matematika 1. Gregor Dolinar. Fakulteta za elektrotehniko Univerza v Ljubljani. 14. november Gregor Dolinar Matematika 1

Delovanje procesorja AVR

PONOVITEV SNOVI ZA 4. TEST

Booleova algebra. Izjave in Booleove spremenljivke

Funkcije. Matematika 1. Gregor Dolinar. Fakulteta za elektrotehniko Univerza v Ljubljani. 21. november Gregor Dolinar Matematika 1

Osnove elektrotehnike uvod

Zaporedja. Matematika 1. Gregor Dolinar. Fakulteta za elektrotehniko Univerza v Ljubljani. 15. oktober Gregor Dolinar Matematika 1

IZPIT IZ ANALIZE II Maribor,

matrike A = [a ij ] m,n αa 11 αa 12 αa 1n αa 21 αa 22 αa 2n αa m1 αa m2 αa mn se števanje po komponentah (matriki morata biti enakih dimenzij):

Osnove programiranja PIC16FXXX družine mikrokontrolerjev

Kotne in krožne funkcije

Podobnost matrik. Matematika II (FKKT Kemijsko inženirstvo) Diagonalizacija matrik

NEPARAMETRIČNI TESTI. pregledovanje tabel hi-kvadrat test. as. dr. Nino RODE

DISKRETNA FOURIERJEVA TRANSFORMACIJA

Funkcije. Matematika 1. Gregor Dolinar. Fakulteta za elektrotehniko Univerza v Ljubljani. 12. november Gregor Dolinar Matematika 1

UVOD V PROGRAMIRANJE MIKROKRMILNIKOV

1. Trikotniki hitrosti

8. Diskretni LTI sistemi

Kontrolne karte uporabljamo za sprotno spremljanje kakovosti izdelka, ki ga izdelujemo v proizvodnem procesu.

1 Fibonaccijeva stevila

UPORABA MIKROPROCESORSKIH NAPRAV

CM707. GR Οδηγός χρήσης SLO Uporabniški priročnik CR Korisnički priručnik TR Kullanım Kılavuzu

Splošno o interpolaciji

*M * Osnovna in višja raven MATEMATIKA NAVODILA ZA OCENJEVANJE. Sobota, 4. junij 2011 SPOMLADANSKI IZPITNI ROK. Državni izpitni center

1. Έντυπα αιτήσεων αποζημίωσης Αξίωση αποζημίωσης Έντυπο Πίνακας μεταφράσεων των όρων του εντύπου...

Enačba, v kateri poleg neznane funkcije neodvisnih spremenljivk ter konstant nastopajo tudi njeni odvodi, se imenuje diferencialna enačba.

Transformator. Delovanje transformatorja I. Delovanje transformatorja II

ALE. Osnove računalniške arhitekture. Ukazi. Operandi. Zgodobina razvoja računalnikov. Glavni. pomnilnik. Vhodo/izhodni sistem

13. Jacobijeva metoda za računanje singularnega razcepa

SKUPNE PORAZDELITVE VEČ SLUČAJNIH SPREMENLJIVK

Kvantni delec na potencialnem skoku

Reševanje sistema linearnih

Integralni račun. Nedoločeni integral in integracijske metrode. 1. Izračunaj naslednje nedoločene integrale: (a) dx. (b) x 3 +3+x 2 dx, (c) (d)

1. Definicijsko območje, zaloga vrednosti. 2. Naraščanje in padanje, ekstremi. 3. Ukrivljenost. 4. Trend na robu definicijskega območja

V tem poglavju bomo vpeljali pojem determinante matrike, spoznali bomo njene lastnosti in nekaj metod za računanje determinant.

4. Osnovne vhodno/izhodne enote

Delovna točka in napajalna vezja bipolarnih tranzistorjev

Osnove matematične analize 2016/17

Tabele termodinamskih lastnosti vode in vodne pare

Kotni funkciji sinus in kosinus

Numerično reševanje. diferencialnih enačb II

Mikrokrmilnik ARM. Matjaž Vidmar, S53MV

Arduino grafični vmesnik

Definicija. definiramo skalarni produkt. x i y i. in razdaljo. d(x, y) = x y = < x y, x y > = n (x i y i ) 2. i=1. i=1

VEKTORJI. Operacije z vektorji

Matematika. Funkcije in enačbe

Priprava na ustni izpit ARS2

Algebraične strukture

Matrike. Poglavje II. Matrika je pravokotna tabela realnih števil. Na primer: , , , 0 1

Uvod v L A TEX 2ε. Osnove pisanja poročil. Špela Bolka. Ljubljana, 21. marec 2013

Matematika 1. Gregor Dolinar. 2. januar Fakulteta za elektrotehniko Univerza v Ljubljani. Gregor Dolinar Matematika 1

Frekvenčna analiza neperiodičnih signalov. Analiza signalov prof. France Mihelič

II. LIMITA IN ZVEZNOST FUNKCIJ

p 1 ENTROPIJSKI ZAKON

Univerza v Ljubljani Fakulteta za računalništvo in informatiko MATEMATIKA. Polona Oblak

Εντολές PIC16F rrf <όνομα καταχωρητή>,a a=f ή a=w H εντολή πραγματοποιεί ολίσθηση προς τα δεξιά του καταχωρητή που ακολουθεί μέσω κρατουμένου

Funkcije več spremenljivk

Matematika 1. Gabrijel Tomšič Bojan Orel Neža Mramor Kosta

Zajemanje merilnih vrednosti z vf digitalnim spominskim osciloskopom

Spoznajmo sedaj definicijo in nekaj osnovnih primerov zaporedij števil.

REˇSITVE. Naloga a. b. c. d Skupaj. FAKULTETA ZA MATEMATIKO IN FIZIKO Oddelek za matematiko Verjetnost 2. kolokvij 23.

Programski jezik C# zanke

2. ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΤΩΝ ΘΥΡΩΝ ΕΙΣΟ ΟΥ/ΕΞΟ ΟΥ ΤΟΥ PIC16F877-ΑΡΙΘΜΗΤΙΚΕΣ ΕΝΤΟΛΕΣ

POMNILNIK POMNILNIK...1

+105 C (plošče in trakovi +85 C) -50 C ( C)* * Za temperature pod C se posvetujte z našo tehnično službo. ϑ m *20 *40 +70

POROČILO 3.VAJA DOLOČANJE REZULTANTE SIL

1. ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΤΟΥ ΜΙΚΡΟΕΛΕΓΚΤΗ PIC16F877

Izpeljava Jensenove in Hölderjeve neenakosti ter neenakosti Minkowskega

PROCESIRANJE SIGNALOV

OSNOVE PROGRAMSKEGA JEZIKA C NA PRIMERU MIKROKRMILNIKA ARM7

KRMILJENJE MIKROKRMILNIŠKEGA MODULA ARDUINO IN NJEGOVA UPORABA PRI KOMUNIKACIJI Z OSTALIMI NAPRAVAMI

TEORIJA LINIJSKIH KOD

Fazni diagram binarne tekočine

D f, Z f. Lastnosti. Linearna funkcija. Definicija Linearna funkcija f : je definirana s predpisom f(x) = kx+n; k,

UNIVERZITET U NIŠU ELEKTRONSKI FAKULTET SIGNALI I SISTEMI. Zbirka zadataka

UNIVERZA V LJUBLJANI PEDAGOŠKA FAKULTETA SANDRA BOLTA LASTNE VREDNOSTI GRAFA DIPLOMSKO DELO

ELEKTRONIKA PAHOR D.O.O.

Inverzni problem lastnih vrednosti evklidsko razdaljnih matrik

diferencialne enačbe - nadaljevanje

Uporabna matematika za naravoslovce

Vaje: Električni tokovi

Tema 1 Osnove navadnih diferencialnih enačb (NDE)

vezani ekstremi funkcij

SEMINARSKA NALOGA Funkciji sin(x) in cos(x)

Εντολές PIC16F887. Reg1=b' ' b' '

ADS sistemi digitalnega snemanja ADS-DVR-4100D4

; Έλεγχος σημαίας λήψης (RCIF=0: άδειος buffer)

Na pregledni skici napišite/označite ustrezne točke in paraboli. A) 12 B) 8 C) 4 D) 4 E) 8 F) 12

Multivariatna analiza variance

Matematika vaja. Matematika FE, Ljubljana, Slovenija Fakulteta za Elektrotehniko 1000 Ljubljana, Tržaška 25, Slovenija

Analiza 2 Rešitve 14. sklopa nalog

ELEKTRONIKA PAHOR D.O.O.

Transcript:

Laboratorijske vaje pri Integralnih proizvodnih sistemih Boštjan Murovec 28. oktober 2002

Kazalo 1 Mikrokrmilniki Microchip 1 1.1 Harvard arhitektura........................ 1 1.2 Podatkovni pomnilnik...................... 2 1.3 Programski pomnilnik...................... 6 1.3.1 Vloga in manipulacija registra PC............ 7 1.3.2 Programski sklad..................... 9 1.3.3 Programski pomnilnik družine PIC18.......... 13 1.4 Nabor ukazov........................... 14 1.4.1 Ukazi za vpis in pomik vrednosti............ 16 1.4.2 Skoki in podprogrami................... 17 1.4.3 Aritmetične operacije................... 21 1.4.4 Logične operacije..................... 30 1.4.5 Ostali ukazi........................ 40 1.5 Posredno naslavljanje....................... 42 1.6 Izdelava tabel........................... 44 1.7 Izvajanje prekinitev........................ 49 1.7.1 Programiranje prekinitvenega podprograma...... 52 2 Naprave z mikrokrmilniki 57 2.1 Napajanje in inicializacija.................... 58 2.2 Izvedba takta........................... 58 2.3 Vhodno/izhodni kontakti..................... 59 2.3.1 Kontakti skupine PORTA................ 60 2.3.2 Primeri uporabe kontaktov PORTA........... 60 2.3.3 Izvedba kontaktov skupine PORTA........... 67 2.3.4 Kontakti skupine PORTB................ 73 2.4 Priklop naprav na digitalne kontakte.............. 75 2.4.1 Priklop LED diode.................... 75 2.4.2 Priklop 7-segmentnih LED prikazovalnikov....... 76 2.4.3 Uporaba RELE-jev.................... 87 2.4.4 Uporaba tranzistorskih stikal.............. 88 2.4.5 Priklop enosmernih motorjev.............. 92 2.4.6 Motorji z večjo napajalno napetostjo.......... 93 2.5 Nastavljiva bremenska napetost................. 94 2.6 Napetostni primerjalnik..................... 97 2.7 Krmiljenje izmeničnih porabnikov................ 99 i

ii KAZALO

Poglavje 1 Mikrokrmilniki Microchip Podjetje Microchip (www.microchip.com) izdeluje široko paleto mikrokrmilnikov, ki so primerni za različne aplikacije. Delijo se v pet družin: PIC12, PIC14, PIC16, PIC17, PIC18, kjer večja številka pomeni zmogljivejše mikrokrmilnike. Družine se razlikujejo po zmogljivosti mikroprocesorja in po množici vgrajenih funkcij. V nadaljevanju si bomo ogledali skupne značilnosti posameznih družin in najpomembnejše razlike med njimi. 1.1 Harvard arhitektura Pomnilnik vseh PIC mikrokrmilnikov je zasnovan po načelu Harvard arhitekture, ki jo prikazuje slika 1.1. V integriranem vezju se nahajata dva ločena pomnilnika, od katerih se en uporablja izključno za pomnenje podatkov, drugi pa je namenjen pomnenju programa, ki ga mikrokrmilnik izvaja. Med obema pomnilnikoma vsebine ne moremo neposredno prenašati. Slika 1.1: Harvard arhitektura mikrokrmilnikov PIC. Do tega trenutka je v vse PIC mikrokrmilnike vgrajen 8-bitni mikroprocesor, zato je širina besede podatkovnega pomnilnika enaka 8 bitov in podatkovni pomnilnik je z mikroprocesorjem povezan preko 8-bitnega vodila, kar je na sliki simbolično označeno. Širina besede programskega pomnilnika ni pri vseh družinah mikrokrmilnikov enaka, ampak je odvisna od števila bitov s katerimi so zapisani ukazi, 1

2 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP ki jih določen mikrokrmilnik uporablja. Mikrokrmilniki zmogljivejše družine PIC18 poznajo dosti več ukazov od ostalih družin, zato potrebujejo večjo (16-bitno) širino programskega pomnilnika kakor ostale družine (12-bitno pri PIC12 ali 14-bitno pri preostalih družinah). Na ta način lahko mikroprocesor prebere večino ukazov v enem bralnem ciklu. Hitrost izvajanja programa je zato večja, kakor pri klasičnem 8-bitnem programskem pomnilniku, kjer je potrebno večjo ali manjšo množico ukazov zajemati v dveh ali več ločenih bralnih ciklih. Zaradi harvard arhitekture sta širini podatkovnega in programskega pomnilnika povsem neodvisni. Tudi naslovna prostora se ne prekrivata. Primer: če mikroprocesor bere ukaz iz naslova 11, to pomeni naslov 11 v programskem pomnilniku. V kolikor za izvedbo ukaza potrebujemo dodaten podatek (operand), se le ta prebere iz podatkovnega pomnilnika. Npr. operand preberemo z naslova 11 (enakost naslovov je zgolj naključje tega primera), to pomeni naslov v podatkovnem pomnilniku. Na noben način mikroprocesor ne more brati ukazov iz podatkovnega pomnilnika, prav tako ukazi ne morejo brati operandov iz ali jih zapisovati v programski pomnilnik. Edino odstopanje od tega pravila predstavlja možnost izgradnje podatkovnih tabel v programskem pomnilniku, kar omogočata družini PIC17 in PIC18. 1.2 Podatkovni pomnilnik Mikrokrmilniki PIC imajo vgrajen RISC mikroprocesor. Za mikroprocesorje, ki temeljijo na RISC arhitekturi, je značilno veliko število registrov ter ukazi naloži/shrani (angl. load/store), ki vrednosti registrov prenašajo iz/v notranji pomnilnik. Mikroprocesor zna izvajati operacije samo nad registri, ničesar pa ne more početi neposredno s podatkovnim pomnilnikom. Pri PIC mikrokrmilnikih so zadeve poenostavljene, saj je ves podatkovni pomnilnik je narejen v obliki množice oziroma banke registrov (angl. register bank, register file), ki so mikroprocesorju dostopni neposredno. Na ta način postanejo ukazi naloži/shrani nepotrebni. To je za uporabnika ugodno, saj je na ta način programiranje mikrokrmilnikov lažje, pa tudi izvajanje programov je hitrejše. Ukazi naloži/shrani se praktično pri vseh mikroprocesorjih, kjer so uporabljani, izvajajo počasneje od ukazov, ki delujejo neposredno z registri. Slabost mikroprocesorjev, ki kot pomnilnik uporabljajo izključno banko registrov, je, da pomnilnik težko razširimo, če nam vgrajena količina ne zadostuje. To je za splošno namenske mikroprocesorje huda omejitev, pri aplikacijah z mikrokrmilniki pa največkrat nimamo velikih pomnilniških zahtev, zato je taka zasnova primernejša. Primer banke registrov, ki jo uporabljajo nekateri krmilniki družine PIC12, prikazuje slika 1.2

1.2. PODATKOVNI POMNILNIK 3 Slika 1.2: Primer banke registrov. Prikazana banka vsebuje 32 (20h) 8-bitnih registrov, ki zavzemajo naslovni prostor od 0 (00h) do 31 (1Fh). Mikroprocesor lahko bere in zapisuje vrednosti vsakega izmed prikazanih registrov na povsem enoten način. Banka registrov se deli na dva dela. Prvi del, ki zavzema naslove od 0 (00h) do 6 (06h), sestavljajo registri, ki imajo poseben namen oziroma funkcijo (posebno namenski registri, angl: special file registers, SFR). Drugi del, ki se razteza od naslova 7 (07h) do 31 (1Fh), pa predstavlja splošno namenski pomnilnik. S stališča mikroprocesorja ta delitev ne obstaja, saj so zanj vsi registri enako dostopni. Delitev je pomembna zato, ker z vpisom vrednosti v enega od posebno namenskih registrov krmilimo oziroma nadziramo delovanje perifernih vezij v mikrokrmilniku, medtem ko vpis in branje vrednosti splošno namenskih registrov nima stranskih učinkov. Primer: register TMR0 (časovnik 0, angl: timer 0) vsebuje vrednost števca, ki se uporablja za izvedbo časovnika. Če vanj vpišemo npr. vrednost 0, časovnik zbrišemo (inicializiramo). Podoben primer predstavlja register OSCCAL (angl. oscillator calibration), ki omogoča fino nastavitev internega oscilatorja z nominalno frekvenco 4MHz. Večjo vrednost kot vpišemo v register OSCCAL, z večjo frekvenco bo oscilator osciliral. S tem ko nadziramo delovanje perifernih vezij z branjem in vpisovanjem vrednosti v posebne registre, se zasnova celotnega mikrokrmilnika močno poenostavi, saj odpadejo posebni ukazi za delo s perifernimi enotami. Primer: namesto, da bi mikroprocesor poznal poseben ukaz za izbris časovnika ali nastavitev oscilatorja, se isti učinek doseže z vpisom vrednosti v podatkovni pomnilnik. Posebne registre torej uporabljamo za nadziranje delovanja mikrokrmilnika, v splošno namenski del banke registrov pa shranjujemo vrednosti spremenljivk, ki jih naš program potrebuje za izvajanje.

4 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP Na istem principu je implementiran pomnilnik vseh družin mikrokrmilnikov PIC, le da je pri zmogljivejših modelih število posebnih in splošnih registrov dosti večje od predstavljenega. Oglejmo si primer podatkovnega pomnilnika zmogljivejšega modela PIC16C745, ki je prikazan na sliki 1.3. Pri tem modelu je obseg pomnilnika že na pogled precej večji. Pomnilnik je razdeljen v štiri banke, od katerih vsaka vsebuje do 128 (80h) registrov. V vsaki banki zasedajo posebni registri naslovni prostor od 0 (00h) do 31 (1Fh). Njihovo povečano število govori o tem, da vsebuje obravnavani mikrokrmilnik dosti več vgrajenih funkcij kot predhodno prikazani model. Lokacije, ki so na sliki zatemnjene, v integriranem vezju niso implementirane in vedno vsebujejo vrednost 0. V prvih treh bankah je naslovni prostor od 32 (20h) do 127 (7Fh) namenjen splošni uporabi, medtem ko je skoraj ves prostor v zadnji banki namenjen medpomnilniku za izvedbo komunikacije preku USB vodila, za kar je strojna podpora v ta mikrokrmilnik že vgrajena. V določenem trenutku je programsko dostopna samo ena banka, ker programski ukazi omogočajo naslavljanje pomnilnika s sedmimi biti, kar pokriva 2 7 = 128 pomnilniških lokacij. Katero banko v danem trenutku uporabljamo, določimo z bitoma RP0 in RP1 (bita 5 in 6) v registru STATUS (naslov 3), kakor prikazuje tabela 1.1. RP0 RP1 banka 0 0 0 1 0 1 0 1 2 1 1 3 Tabela 1.1: Izbira aktivne banke. S slike 1.3 je razvidno, da je register STATUS prisoten v vseh bankah, kar pomeni, da je dostopen neodvisno od tega, katera banka je aktivna. Isto velja za nekatere druge registre (npr. PCL na naslovu 2, FSR na naslovu 4), katerih funkcijo bomo spoznali v nadaljevanju. Podobno lastnost ima zadnjih 16 lokacij vsake banke, ki vsebujejo isto vrednost neodvisno od tega, katera banka je aktivna. Na ta način lahko uporabnik dostopa do pogosto uporabljenih splošno namenskih spremenljivk neodvisno od aktivne banke. Primer dela z bankami. V zlog banke 0 na naslovu 32 (20h) želimo vpisati vrednost 75. V kolikor banka 0 ni aktivna, najprej v registru STATUS nastavimo vrednost bitov (RP0,RP1) na vrednost (0,0). (Kako nastavljamo vrednosti bitov in vpisujemo vrednosti v pomnilnik bomo spoznali kasneje, ko bomo opisali programske ukaze.) Sedaj lahko izvedemo vpis vrednosti 75 na naslov 32. Nadalje želimo vpisati vrednost 98 v lokacijo na naslovu 160

1.2. PODATKOVNI POMNILNIK 5 Slika 1.3: Podatkovni pomnilnik mikrokrmilnika PIC16C745.

6 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP (A0h), ki se nahaja v banki 1. Najprej nastavimo vrednost bitov (RP0,RP1) na (1,0). S tem so naslovi od 128 (80h) do 255 (FFh), ki pripadajo banki 1, preslikani v območje med 0 in 127. Lokacija 160 (A0h) je s tem presikana v naslov 32 (160 128 = 32). Željeno vrednost 98 torej vpišemo na preslikani naslov 32. S tem vsebine pomnilnika v banki 0 nismo spremenili. Če sedaj bita RP0 in RP1 izbrišemo, s čimer ponovno aktiviramo banko 0, bomo iz naslova 32 prebrali vrednost 75. V zvezi s podatkovnim pomnilnikom omenimo še, da ima družina PIC18 njegovo kapaciteto precej večjo (do 1,5kB). Naslavljamo ga 8-bitno, kar pomeni, da lahko hkrati uporabljamo 2 8 = 256 pomnilniških lokacij. Izbira banke poteka z vpisom vrednosti v posebno namenski register, kar je učinkoviteje od nastavljanja vrednosti posameznih bitov, poleg tega so vsi posebno namenski registri dostopni neodvisno od aktivne banke, kar programiranje mikrokrmilnikov močno poenostavi. 1.3 Programski pomnilnik Programski pomnilnik je namenjen hranjenju ukazov, ki sestavljajo mikrokrmilniški program. Njegova velikost in organizacija se nekoliko razlikujeta med posameznimi družinami. Slika 1.4 prikazuje programski pomnilnik že omenjenega modela PIC16C745. Programski pomnilnik se vedno prične na naslovu 0 (0000h) in se zvezno nadaljuje do zadnje pomnilniške lokacije, ki je v prikazanem primeru 8191 (1FFFh). Kapaciteta prikazanega pomnilnika je 8k besed, od katerih vsaka lahko pomni 14-bitni ukaz. S slike 1.4 je razvidno, da imata dve lokaciji na prvi strani programskega pomnilnika posebno vlogo. Prva lokacija se nahaja na naslovu 0 (0000h) in se imenuje inicializacijski vektor (angl. reset vector). Ob izvedbi inicializacije iz kakršnegakoli razloga (npr. ob vklopu napajanja) se v register PC vpiše vrednost 0, s čimer se zagotovi, da se mikrokrmilniški program vedno prične izvajati na naslovu 0. Inicializacijski vektor imajo vsi mikroprocesorji vseh proizvajalcev, saj brez njega ne bi bilo možno določiti, na kateri lokaciji se program prične izvajati. Ni pa nujno, da se pri vseh nahaja na naslovu 0, kakor je slučaj pri mikrokrmilnikih PIC. Druga posebna lokacija se nahaja na naslovu 4 (0004h) in se imenuje prekinitveni vektor (angl. interrupt vector). Na tem naslovu se prične izvajati prekinitveni podprogram, ki ga sproži katerikoli zunanji dogodek, ki smo ga konfigurirali za sprožitev prekinitve. Primer: mikrokrmilnik nadzoruje temperaturo vode v peči za centralno ogrevanje. Če temperatura naraste preko 90, temperaturni senzor sproži prekinitev s spremembo nivoja na

1.3. PROGRAMSKI POMNILNIK 7 Slika 1.4: Primer programskega pomnilnika PIC16C745. ustreznem kontaktu mikrokrmilnika, kar povzroči izvajanje prekinitvenega podprograma na naslovu 4. Brez prekinitev bi moral mikrokrmilnik stalno odčitavati temperaturo senzorja, da bi zaznal prekoračitev. Namesto tega lahko počne druge stvari in se na prekoračitev temperature odzove samo takrat, ko se zgodi ustrezen zunanji dogodek. Podrobnejši opis izvajanja prekinitev podajamo v razdelku 1.7. 1.3.1 Vloga in manipulacija registra PC Pri izvajanju programa ima ključno vlogo programski števec PC (angl. program counter), ki vsebuje naslov programskega pomnilnika, s katerega mora mikroprocesor prebrati ukaz za izvršitev. Po izvedbi vsakega ukaza se vrednost registra PC poveča za 1, s čimer se izvajanje programa pomakne na naslednji ukaz. Skoki v programih se realizirajo tako, da se v register PC vpiše naslov ukaza, kamor skačemo. S tem se izvajanje programa nadaljuje na novem naslovu. Primer: na naslovu 437 se nahaja ukaz za skok na naslov 217. Vse kar ta ukaz naredi je, da v register PC zapiše vrednost 217. Naslednji ukaz,

8 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP ki ga bo mikroprocesor izvršil, bo prebran z naslova 217 in ne z naslova 438. Za tem bo na vrsti ukaz na naslovu 218, in tako naprej po vrsti, dokler spet ne naletimo na ukaz za izvedbo skoka. Pri mikrokrmilnikih družine PIC16 je register PC širok 13 bitov, kar omogoča naslavljanje vseh 8192 pomnilniških lokacij (2 13 = 8192), ki jih programski pomnilnik vsebuje. Registrer PC je delno dostopen za branje in vpisovanje. Vrednost njegovih spodnjih 8 bitov se nahaja v posebno namenskem registru PCL (angl. PC low), ki se v vseh bankah podatkovnega pomnilnika nahaja na naslovu 2 (slika 1.3 na strani 5). Zgornjih 5 bitov ni neposredno dostopnih za branje, vanje je možno le zapisovsti. V ta namen se uporablja posebno namenski register PCLATH (angl. PC latch high), ki predstavlja zatič (angl. latch) za zgornjih 5 bitov registra PC. PCLATH se v vseh bankah nahaja na naslovu 10 (0Ah). Zapis vrednosti v vseh 13 bitov registra PC poteka tako, kot prikazuje slika 1.5. V register PCLATH vpišemo želeno vrednost zgornjih 5 bitov registra PC. S tem vrednosti v register PC še nismo zapisali. Vrednost PCLATH se prenese v PC v trenutku, ko spremenimo vrednost registra PCL. Torej: vrednost v register PC se hkrati prenese iz PCLATH in PCL, pri čimer vpis v slednjega sproži oba vpisa. Slika 1.5: Vpis vrednosti v register PC preko registra PCL. Primer. Register PC vsebuje vrednost 532. To pomeni, da bo sedaj mikroprocesor izvedel ukaz, ki se v programskem pomnilniku nahaja na tem naslovu. Denimo, da je to ukaz, ki v register PCLATH vpiše vrednost 3. Vrednost se zapiše samo v PCLATH in se ne prenese v zgornjih 5 bitov registra PC. Med izvajanjem ukaza se vrednost PC poveča za 1, na povsem običajen način, s čimer smo v programskem pomnilniku dosegli naslov 533. Tu se nahaja ukaz, ki v PCL vpiše vrednost 11. Ker ukaz spreminja vrednost registra PCL, se bo hkrati v zgornjih 5 bitov prenesla vsebina registra PCLATH. Po izvedbi ukaza bo register PC vseboval vrednost PCL + 256 PCLATH = 11 + 256 3 = 779. S tem smo izvedli programski

1.3. PROGRAMSKI POMNILNIK 9 skok na naslov 779, kar pomeni, da se bo naslednji ukaz prebral s tega naslova in ne z naslova 534. Izvajanje programskih skokov na ta način je interesantno, saj ni treba, da skočimo na v vnaprej vpisan naslov v programu. Cilj skoka lahko izračunamo in nato vpišemo v registra PCLATH/PCL, s čimer se odpira cel spekter programskih trikov. Eden od njih je izdelava indeksiranih tabel, kakor je prikazano v poglavju 1.6. Vendar bi bilo programiranje težavno, če bi morali prav vsak skok izvesti na ta način. Namesto tega pozna mikroprocesor poseben ukaz goto, ki je enostavnejši za uporabo, kadar ciljnega naslova ni potrebno izračunati, ampak je le-ta znan vnaprej, kar je najpogostejši slučaj. Na žalost ukaz goto ne omogoča specifikacije celotnega 13 bitnega naslova, kamor skačemo. Razlog je preprost: ukazi so dolgi 14 bitov, zato bi pri 13 bitnem naslovu ostal samo en bit za določitev kode ukaza, kar je premalo. Za določanje naslova je pri ukazih za izvedbo skoka predvidenih 11 bitov, kar pokriva 2048 pomnilniških lokacij (2 11 = 2048). Od tu sledi delitev pomnilnika na štiri strani (8192/2048 = 4), kakor je prikazano na sliki 1.4 (stran 7). Pri specifikaciji celotnega naslova nam zopet priskoči na pomoč register PCLATH (sliki 1.6). Vrednost spodnjih 11 bitov registra PC določi ukaz, zgornja dva bita pa se preneseta iz tretjega in četrtega bita registra PCLATH, s čimer PCLATH določa stran, na katero skačemo. Če je naš program dovolj kratek, da se v celoti nahaja na prvi strani, sta ta dva bita lahko vedno izbrisana in programski skok opravimo brez vsakih zapletov. Slika 1.6: Vpis vrednosti v register PC preko ukaza goto. 1.3.2 Programski sklad Poleg opisanih programskih skokov potrebujemo tudi klice podprogramov, čemur sta namenjena ukaza call in return. Pri skoku v podprogram ravno

10 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP tako vpišemo vrednost ciljne lokacije v register PC, kakor pri ukazu goto. Vendar moramo pri klicu podprograma pred tem shraniti staro vrednost registra PC, da se lahko po koncu podprograma vrnemo na mesto, kjer se je klic izvedel. Ukaz call opravi oboje: najprej shrani vrednost registra PC, nato pa izvede skok na povsem enak način kakor ukaz goto. Iz podprograma se vrnemo z ukazom return, ki ne stori nič drugega, kot da v register PC zapiše vrednost, ki jo je ukaz call predhodno shranil. Praktično vsi mikroprocesorji uporabljajo za shranjevanje naslovov podatkovno strukturo, ki se imenuje sklad (angl. stack). Pri mikroprocesorjih je običajno, da lahko na sklad shranjujemo vrednost vseh pomembnejših registrov. Pri mikrokrmilnikih PIC pa je zaradi Harvard arhitekture možno na sklad shranjevati samo vrednost registra PC, zato v tem primeru govorimo o programskem skladu. Le-ta je prikazan na desnem delu slike 1.4 (stran 7) pod registrom PC. Za delovanje sklada potrebujemo dve stvari: (1) pomnilnik, kamor shranjujemo vrednosti in (2) poseben register, ki mu pravimo kazalec sklada SP (angl. stack pointer). Pri mikrokrmilnikih PIC16 slednji programsko ni dostopen, zato na sliki ni prikazan. Sklad deluje na naslednji način. Dokler vanj še nismo shranili nobene vrednosti (noben ukaz call še ni bil izvršen), kaže register SP na začetek pomnilnika, ki je rezerviran za sklad (na sliki 1.4 je to nivo 0). Ob prvem vpisu vrednosti na sklad (ob izvedbi prvega ukaza call) se nivo 0 zasede, kazalec SP pa se pomakne na nivo 1. Pri drugem vpisu se zasede nivo 1, kazalec SP pa se pomakne na nivo 2. Pri nadaljnjih vpisih vrednosti, se dogajanje ponovi. Vrednosti na skladu lahko uporabimo (z ukazom return) samo v obratnem vrstnem redu, kot smo jih vanj shranili. Zaradi takega delovanja pravimo skladu LIFO (angl. last in fist out) struktura. Če smo do tega trenutka vpisali dve vrednosti in se SP nahaja na nivoju 2, se le-ta ob branju pomakne na nivo 1, s čimer zapisano vrednost lahko preberemo. S tem smo nivo 1 sprostili in smatramo, da je prazen, kar pomeni da bo ta nivo cilj naslednjega vpisa, v kolikor vmes ne bo praznenja dodatnih nivojev. Oglejmo si naslednji primer. Ob pričetku izvajanja programa je sklad prazen, tako kot prikazuje slika 1.7. Kazalec sklada SP kaže na nivo 0. V glavnem programu (beseda glavni označuje, da se ne nahajamo v nobenem podprogramu) hočemo izpisati števko na LCD zaslon. Podprogram izpis stevke, ki to opravi, se nahaja na naslovu 456. V glavnem programu (npr. na naslovu 135) torej pokličemo podprogram za izpis z ukazom call 456. Ukaz call najprej shrani na sklad naslov programskega pomnilnika, kamor se bomo po izvedbi podprograma vrnili. V našem primeru je to naslov 136,

1.3. PROGRAMSKI POMNILNIK 11 Slika 1.7: Prazen sklad. kjer se nahaja prvi ukaz neposredno za ukazom call. Situacijo ponazarja sklad (A) na sliki 1.8. Naslov 136, ki pripada glavnemu programu, je shranjen v prvi nivo sklada. Kazalec sklada SP kaže na naslednjo prosto lokacijo, tako da je sklad pripravljen za shranjevanje naslednje vrednosti. Slika 1.8: Dogajanje na skladu pri izvajanju izpisa. Ko je naslov za vrnitev iz podprograma shranjen, ukaz call vpiše naslov 456 v register PC, enako kot bi to storil ukaz goto, s čimer se podprogram izpis stevke prične izvajati. Denimo, da ta podprogram potrebuje pomoč podprograma pretvori v ASCII, ki številko za izpis pretvori v ASCII kodo znaka za izpis na LCD; ta podprogram se nahaja na naslovu 890. V ta namen

12 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP se v podprogramu izpis stevke (recimo na naslovu 487) nahaja ukaz call 890. Ob izvedbi tega ukaza se zopet shrani naslov za vrnitev iz podprograma ( sklad (B) na sliki 1.8). Na koncu podprograma pretvori v ASCII se nahaja ukaz return, ki naredi naslednje. Najprej se kazalec sklada, ki kaže nezaseden nivo 2, vrne na predhodni nivo 1. Nato se iz tega nivoja prebere naslov za vrnitev, ki se vpiše v register PC. S tem je nivo 1 prost in izvajanje podprograma pretvori v ASCII zaključeno. V PC se je vpisal naslov 488, ki pripada podprogramu izpis stevke, s čimer le-ta nadaljuje izvajanje. Stanje sklada v tem trenutku prikazuje sklad (C) na sliki 1.8. V nadaljevanju potrebuje podprogram izpis stevke pomoč podprograma pisi LCD na naslovu 1315, ki ASCII kodo znaka vpiše v LCD modul. Npr. na naslovu 496 se nahaja ukaz call 1315, s katerim ta podprogram pokličemo. Dogajanje na skladu se ponovi: naslov 497, kamor se bomo vrnili, se zapiše na prvi prosti nivo in register SP pomakne navzdol ( sklad (D) na sliki 1.8). Prej ali pozneje nas return vrne iz podprograma pisi LCD na naslov 497, kjer se nadaljuje izvajanje podprograma izpis stevke ( sklad (E) na sliki 1.8). Ker je izpis pri koncu, kmalu naletimo na ukaz return, ki nas vrne v glavni program na naslov 136. Sedaj je sklad popolnoma prazen, kakor je bil pred klicem podprograma ( sklad (F) na sliki 1.8). Če bi ponovno potrebovali ta ali kakšen drug podprogram, bi bilo dogajanje povsem enako. V mikrokrmilnikih PIC je sklad realiziran v ločenem pomnilniku in ni del uporabniško dostopnega programskega pomnilnika. Razlog za tako izvedbo je trojen: (1) pri večini PIC mikrokrmilnikov je v programski pomnilnik nemogoče pisati med izvajanjem programa, saj je le-ta realiziran kot EPROM ali ROM, (2) skok v podprogram ali vrnitev iz njega se izvede hitreje, ker ni potrebno vsebine registra PC shraniti v ali prebrati iz programskega pomnilnika, za kar bi potrebovali dodaten zapisovalni oziroma bralni cikel, (3) širina registra PC in s tem velikost naslovnega prostora je neodvisna od širine besede programskega pomnilnika. Slabost ločene zasnove sklada je v tem, da je globina sklada (število lokacij, ki si jih lahko zapomnimo) tovarniško omejena in jo na noben način ne moremo razširiti. Družina PIC12 ima sklad globine dveh nivojev, PIC16 vsebuje osem ter PIC18 dvaintrideset nivojev. Velikost sklada neposredno določa, do kakšne globine lahko kličemo podprograme. Če bi v predhodnem primeru podprogram pretvori v ASCII potreboval tretji podprogram, ta pa spet četrtega,... in tako naprej preko globine osem, bi prišlo do prekoračitve sklada. Register SP je 3-bitni binarni števec, zato bi se ob prehodu z nivoja 7 = 111 2 na nivo 8 = 1000 2, v SP vpisali samo spodnji trije biti številke 8, kar je 0 = 000 2. Nova vrednost bi se

1.3. PROGRAMSKI POMNILNIK 13 na sklad vpisala preko že zasedenega nivoja 0, s čimer bi izgubili informacijo o tem, kam naj se v glavni program vrnemo. Ob izhodu iz podprograma v glavni program, bi se delovanje mikrokrmilnika sesulo. V primeru, da mikrkokrmilnik nadzoruje napravo, ki lahko poškoduje človeka ali povzroči gmotno škodo, so lahko posledice katastrofalne. Za preprečitev takih situacij imajo PIC mikrokrmilniki vgrajeno možnost avtomatične (re)inicializacije v primeru prekoračitve obstoječih nivojev sklada. 1.3.3 Programski pomnilnik družine PIC18 Za primerjavo si oglejmo še programski pomnilnik modela PIC18C452, ki spada v družino PIC18 (slika 1.9). Vidmo, da je pri tem modelu pomnilnik dosti večji. Njegova kapaciteta je 32768B, ki se razteza preko naslovnega prostora od 0 (0000h) do 32767 (7FFFh). Pomnilnik je z mikroprocesorjem povezan s 16-bitnim vodilom, ker so ukazi pri družini PIC18 dolgi 16 bitov. Kljub temu lahko v pomnilniku naslavljamo posamezne zloge, ker ta družina omogoča izdelavo podatkovnih tabel (npr. tabela ASCII znakov, tabela vrednosti funkcije sinus,...) v programskem pomnilniku. Za branje takih tabel so predvideni posebni ukazi, ki jih modeli družine PIC16 nimajo. Mikrokrmilniki PIC18 imajo 21-bitni register PC, kar omogoča naslavljanje 2 21 = 2.097.152 = 2MB pomnilnika. To je dosti več od vgrajene kapacitete 32kB. Tako velik register PC je predviden za modele, v katere bo vgrajeno mikroprocesorsko vodilo, preko katerega bo možno priklopiti dodaten zunanji pomnilnik. V tem trenutku tega ne omogoča noben mikrokrmilnik PIC18. Branje področja v pomnilniku, ki ne obstaja, vedno vrne vrednost 0, tako kot prikazuje slika 1.9. Družina PIC18 ima možnost uporabe dvonivojske prioritete prekinitev. Za vsak prekinitveni dogodek lahko določimo ali spada v razred visoko ali nizko prioritetnih prekinitev. Med izvajanjem prekinitve z nizko prioriteto se lahko sproži prekinitev z visoko prioriteto, obratno pa ne. Zaradi dveh prioritetnih nivojev obstajajta dva prekinitvena vektorja. Na naslovu 8 (0008h) se nahaja podprogram visoko prioritetnih prekinitev, medtem ko se na naslovu 24 (0018h) pričnejo izvajati nizko prioritetne prekinitve. Družina PIC18 ima razširjen tudi programski sklad, ki je velik 32 nivojev. Na ta način smo pri klicanju podprogramov dosti manj omejeni kot pri družini PIC16.

14 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP Slika 1.9: Primer programskega pomnilnika PIC18C452. 1.4 Nabor ukazov Mikrokrmilniki PIC imajo relativno preprost nabor ukazov, ki delujejo neposredno nad katerimkoli registrom podatkovnega pomnilnika oziroma trenutno aktivne banke. Mikrokrmilnik vsebuje tudi poseben delovni register, ki je v specifikacijah označen s črki W (angl. working register). Ta register ima podobno vlogo kot akumulator pri ostalih mikroprocesorjih: vanj se lahko shranjujejo rezultati operacij, ki jih izvajamo. Praktično pri vseh mikroprocesorjih določen nabor ukazov vpliva na statusne bite, kot so indikatorji ničle Z (angl. zero), prenosa C (angl. carry) in prenosa s 3 na 4 bit DC (angl. decimal carry, half carry). Pri PIC mikrokrmilnikih so ti indikatorji predstavljeni s posameznimi biti v registru STATUS. Pri družini PIC16 so razporedi naslednji: bit 0, 1 in 2 predstavlja indikator C, DC in Z. Družina PIC18 pozna poleg gornjega nabora statusnih bitov še indikatorja prekoračitve OV (angl. overflow) in negativnosti N (angl. negative). Nahajata se na 4 in 5 bitu registra STATUS. Vrednosti statusnih bitov vplivajo na izvajanje določenih ukazov, s čimer imamo možnost izvedbe pogojnih stavkov, ki imajo enako funkcijo kakor

1.4. NABOR UKAZOV 15 stavki if v višjih programskih jezikih. Dejansko se pogojni stavki višjih programskih jezikov prevedejo v zbirni jezik tako, da ukazi, ki utelešajo logični pogoj, nastavijo ustrezne indikatorje v registu STATUS, pogojni skok pa v odvisnosti od vrednosti indikatorjev skoči na eno ali drugo mesto. Ko bomo spoznavali pogojne skoke, bomo uporabo statusnih indikatorjev pokazali na konkretnih primerih. Družine PIC12, PIC14 in PIC16 imajo podoben programski model, ki zajema nekaj več kot 30 ukazov. Družini PIC17 in PIC18 pa imata programski model močno razširjen. Zlasti to velja za slednjo, saj le-ta pozna kar 77 ukazov, s čimer je programiranje močno olajšano, pa tudi programi se izvajajo hitreje, saj lahko večkrat z enim ukazom iz nabora PIC18 zamenjamo dva ali več ukazov iz nabora PIC16. Na tem mestu se bomo omejili na programski model družine PIC16, ki je prikazan v tabelah 1.2 in 1.3. Nabor ukazov je relativno preprost, zato ga lahko osvojimo brez težav. Zapomniti si moramo samo nekaj oznak, ki se pri opisu ukazov ponavljajo: k: konstanta (angl. literal); v zbirniku PIC mikrokrmilnikov se konstante pišejo na naslednji način: desetiška konstanta se prične s piko (npr. 67 10 zapišemo kot.67), šestnajstiška konstanta se piše brez dodatkov (npr. 67 10 = 43h zapišemo kot 43), dvojiška konstanta se piše s predpono B in v enojnih narekovajih (npr. 67 10 = 01000011 2 zapišemo kot B 01000011 ), a: konstantni naslov skoka (angl. address); v zbirniku PIC mikrokrmilnikov nam naslove skokov običajno izračuna zbirnik na podlagi oznak (angl. label) programskih stavkov, W: register W, f: naslov v podatkovnem registru (med 0 in 127), d: destinacija oziroma cilj, ki je lahko W ali f, b: bit v zlogu (med 0 in 7) in [x]: vrednost v pomnilniku na naslovu x. Oglejmo si funkcije ukazov po vrsti, kot so navedeni v tabelah. V prvem stolpcu se nahaja ime ukaza in v drugem njegovi operandi. Tretji stolpec opisuje operacijo, ki jo ukaz opravlja. V četrtem stolpcu je označen čas izvajanja ukazov. Številka 1 pomeni, da se ukaz izvaja en ukazni cikel oziroma štiri taktne cikle, ker mikrokrmilnik izvede po en ukaz v štirih periodah takta. Pri frekvenci ure 4MHz številka 1 pomeni, da se ukaz izvaja 1µs, pri 40MHz pa 100ns. Številka 2 pomeni dvakrat toliko časa.

16 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP ukaz operacija čas status vpis in premik vrednosti movlw k W k 1 movwf f f W 1 movf f,d d f 1 Z clrf f f 0 1 Z clrw W 0 1 Z swapf f,d zamenjava bitov 3:0 in 7:4 1 skoki in podprogrami goto a skoči na naslov a 2 call a pokliči podprogram na naslovu a 2 return vrni se iz podprograma 2 retlw a W a; vrni se iz podprograma 2 retfie izhod iz prekinitvenega pod. 2 btfsc f,b če f<b>= 0, preskoči 1(2) btfss f,b če f<b>= 1, preskoči 1(2) aritmetične operacije decf f,d d f 1 1 Z incf f,d d f + 1 1 Z decfsz f,d d f 1; preskoči, če d = 0 1(2) incfsz f,d d f + 1; preskoči, če d = 0 1(2) addlw k W k + W 1 C,DC,Z addwf f,d d f + W 1 C,DC,Z sublw k f k W 1 C,DC,Z subwf f,d d f W 1 C,DC,Z Tabela 1.2: Nabor ukazov družine PIC16 (prvi del). Zadnji stolpec v tabeli navaja statusne bite, ki jih ukaz nastavi glede na rezultat operacije. Če je stolpec prazen, ukaz ne vpliva na noben statusni bit. 1.4.1 Ukazi za vpis in pomik vrednosti Ukaz: MOVLW K Ukaz movlw k (move literal to W) vpiše vrednost k v register W. Primer: movlw.54, vpiše v register W vrednost 54 10. Ukaz: MOVWF F Ukaz movwf f (move W to file register) vpiše vrednost registra W v zlog podatkovnega pomnilnika na naslovu f. Primer: register W vsebuje vrednost 92 10 ; po izvedbi ukaza movwf.34, bo vrednost 92 10 vseboval tudi zlog na naslovu 34 10.

1.4. NABOR UKAZOV 17 Ukaz: MOVF F, D Ukaz movf f, d (move f ile register) prenese vsebino podatkovnega pomnilnika na naslovu f v destinacijo d, ki je lahko w ali f. V prvem primeru se vrednost podatkovnega pomnilnika prenese v register W, v drugem primeru pa se vrednost podatkovnega pomnilnika zapiše ponovno sama vase (torej se nobena vrednost ne spremeni). V obeh primerih se indikator Z nastavi, če je prenešena vrednost enaka 0. Primer: podatkovni pomnilnik na naslovu 45 10 vsebuje vrednost 123 10. Po izvedbi ukaza movf.45,w bo tudi register W vseboval vrednost 123 10. Če bi izvedli ukaz movf.45, f, bi se vrednost 123 10 zapisala sama vase. V obeh primerih bi se indikator Z izbrisal, ker prenešena vrednost ni 0. Tak ukaz lahko uporabimo za hitro testiranje, ali se na določeni lokaciji v podatkovnem pomnilniku nahaja vrednost 0. Ukaza: CLRF F in CLRW Ukaz clrf f (clear file register) vpiše vrednost 0 v lokacijo na naslovu f. Podobno ukaz clrw (clear W) vpiše vrednost 0 v register W. Oba ukaza nastavita indikator Z, ker je prenešena vrednost enaka 0. Ukaz: SWAPF F, D Ukaz swapf f, d (swap file register) zamenja vsebino spodnjih štirih bitov (angl. nibble) vrednosti na lokaciji f z zgornjimi štirimi biti in obratno. Ta ukaz je koristen npr. pri BCD aritmetiki, kjer izvajamo operacije nad posameznimi števkami, ki so zakodirane v skupinah po štiri bite. Parameter d zopet določa, kam se vpiše rezultat zamenjave. Če je le-ta enak w, se bo zlog z zamenjanimi biti vpisal v register W, sicer se bo vpisal v podatkovni pomnilnik preko stare vrednosti. Primer: pomnilnik na naslovu 82 10 vsebuje vrednost 109 10 = 0110 1001 2. Po izvedbi ukaza swapf.82, w se bo v register W vpisala vrednost 150 10 = 1001 0110 2. Ukaz swapf.82, f bi vrednost 150 10 = 1001 0110 2 vpisal nazaj na lokacijo 82 10, register W pa bi ostal nespremenjen. 1.4.2 Skoki in podprogrami Ukaz: GOTO A Ukaz goto a (goto address) brezpogojno skoči na naslov a (skoki med posameznimi stranmi pomnilnika so opisani v poglavju 1.3.1). S tabele je razvidno, da programski skok potrebuje dva ukazna cikla (osem taktnih ciklov),

18 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP kar je dvakrat več časa od večine ostalih ukazov. Velja, da ukazi, ki spremenijo tok programa, potrebujejo dva ukazna cikla, vsi ostali ukazi pa enega. Primer uporabe: večno zanko naredimo na naslednji način: 1. zanka movlw.3 2. movwf.32 3. goto zanka Kot vidimo v prvi vrstici programa, se oznaka programskega stavka izvede na začetku vrstice: v našem primeru smo ukazu priredili oznako zanka. Če določeni vrstici ne želimo prirediti oznake, ostalo vsebino pričnemo pisati zamaknjeno v desno, tako kot v vrsticah 2 in 3. S tem, ko vrstici priredimo oznako, se lahko nanjo sklicujemo, ne da bi poznali dejanski naslov ukaza v programskem pomnilniku, ki se izračuna avtomatično. Zato v vrstici 3, kjer želimo izvesti skok nazaj na vrstico 1, kot argument ukaza goto podamo oznako mesta, kamor skačemo. Delovanje prikazanega programa je naslednje. V vrstici 1 vpišemo vrednost 3 10 v register W. V vrstici 2 to vrednost prenesemo v podatkovni pomnilnik na naslov 32 10. Tretja vrstica povzroči skok na vrstico 1, s čimer se vse zopet ponovi. Izvajanje teh treh vrstic se ponavlja v nedogled. Prikazani program ne počne nič uporabnega, razen da demonstrira uporabo skokov. Ko bomo spoznali več ukazov, bomo prikazali uporabnejše primere. Ukaza: CALL A in RETURN Ukaz call a (call subroutine at address) je po delovanju podoben ukazu goto, le da pred izvedbo skoka shrani vrednost registra PC na sklad. S pomočjo shranjene vrednosti PC lahko z ukazom return (return from subroutine) nadaljujemo izvajanje programa za ukazom call. Zato pravimo, da ukaz call pokliče podprogram, ukaz return pa izstopi iz njega. Delovanje podprogramov je enako klicanju funkcij ali procedur v višjih programskih jezikih; ti klici se dejansko utelešajo preko teh dveh ukazov. Podrobno dogajanje na skladu ob izvajanju ukazov call in return je bilo podano v poglavju 1.3.2, zato bomo na tem mestu opisali dogajanje samo s programerjevega zornega kota. Oglejmo si naslednji primer uporabe podprogramov.

1.4. NABOR UKAZOV 19 1. movlw.15 2. movwf.32 3. call izracun 4.... 30. movlw.99 31. movwf.32 32. call izracun 33.... 80. izracun movf.32,w 81.... 93. return Nekje v programu (vrstice od 80 do 93) obstaja podprogram izracun, ki opravlja bolj ali manj zapleten izračun. V vrstici 80 podprogram prebere vsebino naslova 32 10, kar simbolizira branje parametera za izračun. V vrsticah od 81 do 92 se izračun vrši, kar je nakazano s prekinitvijo zaporedja številk programskih vrstic. Ukaz return v vrstici 93 se vrne v glavni program. V glavnem programu potrebujemo izračun, ki ga opazovani podprogram opravlja. Vrstici 1 in 2 vpišeta parameter (število 15 10 ) v lokacijo 32 10. V vrstici 3 pokličemo podprogram izracun. Ukaz call shrani vrednost registra PC (ki vsebuje naslov vrstice 4) na sklad in izvede skok na vrstico 80. Tu se izračun izvrši, nakar se z ukazom return vrnemo v glavni program, to je na vrstico 4. Sedaj se zopet izvaja glavni program. Nekoliko kasneje zopet potrebujemo isti izračun, le z drugim parametrom (99 10 ), zato v vrsticah 30 in 31 vpišemo njegovo vrednost na ustrezno mesto. V vrstici 32 ponovno pokličemo podprogram izracun. V drugem primeru je dogajanje popolnoma enako: izračun se izvede in ukaz return se vrne na vrstico 33. Primer nakazuje smisel uporabe podprogramov. Dele programa, ki jih potrebujemo večkrat, realiziramo kot podprograme in jih kličemo po potrebi. Uporaba je povsem analogna višjim programskim jezikom, kjer imamo procedure in funkcije za realizacijo celega spektra opravil: delo z datotekami, risanje likov, računanje s kompleksnimi števili,... Klic podprogramov traja dva ukazna cikla, enako kot skoki z ukazom goto, čeprav je pred izvedbo skoka v podprogram potrebno shraniti register PC na sklad. Do dodatne zakasnitve ne pride, ker je sklad implementiran ločeno od programskega pomnilnika, zato shranjevanje vrednosti nanj ne zahteva dodatnega vpisovalnega cikla programskega pomnilnika. Podoben komentar velja za ukaz return, kjer ne potrebujemo dodatnega bralnega cikla.

20 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP Ukaz: RETLW K Za skok iz podprogramov lahko uporabimo tudi ukaz retlw k (angl. return with literal in W). Njegova funkcija je enaka kot pri ukazu return, le da retlw pred izvedbo vrnitve iz podprograma vpiše konstanto k v register W. Primer: ukaz retlw.17 naredi isto kot kombinacija ukazov: movlw.17 in return. Vrednost v registru W lahko obravnavamo kot parameter, ki ga podprogram vrne glavnemu programu (podobno kot funkcija tipa int v jeziku C ali C++). Zamenjava obeh ukazov z enim samim je ugodna, saj so situacije, kjer prenašamo parameter iz podprograma, pogoste, tako da z ukazom retlw skrajšamo in pohitrimo program. Ukaza: BTFSC F, B in BTFSS F, B Ta dva ukaza omogočata izvajanje pogojnih stavkov. Ukaz btfsc f, b (angl. bit test file register and skip if clear) testira vrednost bita b na naslovu f in preskoči naslednji ukaz, če je bit izbrisan. Primer: ukaz btfsc.34,.2 testira vrednost bita 2 10 na naslovu 34 10 in izpusti naslednji ukaz, v primeru, da je vrednost bita enaka 0. Poglejmo si možno uporabo. Zamislimo si, da mikrokrmilniški program nadzoruje delovanje tiskalnika. Na naslovu 62 10 se nahaja spremenljivka, ki ima vrednost 0, če je tiskalnik brez papirja, v nasprotnem primeru pa ima vrednost različno od 0. Naslednji program nam kaže, kako izvedemo programski skok na ustrezno mesto, glede na to, ali tiskalnik ima papir ali ne. 1. movf.62,f 2. btfsc STATUS,Z 3. goto prazno 4. goto polno V prvi vrstici preberemo vsebino naslova 15 10 in jo zapišemo samo vase. Stranski učinek ukaza je, da se nastavi indikator Z, če je vrednost enaka 0. V drugi vrstici testiramo indikator Z (ukaz bi lahko zapisali tudi kot btfsc.3,.2, ker se register STATUS nahaja na naslovu 3 10, indikator Z pa predstavlja bit 2 v njem) in spustimo naslednji ukaz, če je le-ta izbrisan. Torej: če je indikator Z izbrisan (tiskalnik ima papir), preskočimo ukaz goto prazno in izvršimo ukaz goto polno. Če je indikator Z nastavljen (tiskalnik nima papirja), se noben ukaz ne preskoči, zato izvršimo ukaz goto prazno.

1.4. NABOR UKAZOV 21 Ukaz btfss f, b (angl. bit test file register and skip if set) je zelo podoben: testira vrednost bita b na naslovu f in preskoči naslednji ukaz, če je bit nastavljen. Oba ukaza se izvajata en ukazni cikel, če preskoka ni in dva ukazna cikla v nasprotnem primeru. Izvajanje pogojev z opisanima ukazoma je interesantno iz dveh razlogov. (1) Navadno mikroprocesorji omogočajo samo pogojni preskok ukazov, ki izvajajo skoke v programu (goto, call,...), kar ni slučaj pri mikrokrmilnikih PIC, kjer lahko preskočimo poljuben ukaz. (2) Največkrat mikroprocesorji omogočajo samo testiranje statusnih bitov Z, C, DC, N, OV, ne pa bitov v registrih oziroma pomnilniku. To zopet ne velja za mikrokrmilnike PIC, saj lahko testiramo poljuben bit v podatkovnem pomnilniku oziroma v trenutno aktivni banki. To omogoča številne prostorske in časovne optimizacije. Oglejmo si fragment programa, ki demonstrira oba primera. Nahajamo se v podprogramu, ki v registru W vrne vrednost 2 10, če je vrednost na lokaciji 78 10 deljiva z dva, sicer vrne vrednost 1 10. 1. btfss.78,.0 2. retlw.2 3. retlw.1 V prvi vrstici testiramo, ali ima vrednost na naslovu 78 10 nastavljen najnižji bit. Če je temu tako, številka ni deljiva z dva in vrniti moramo vrednost 1. Zato preskočimo ukaz v drugi vrstici in se v glavni program vrnemo z ukazom v tretji vrstici. V nasprotnem primeru do preskoka ne pride in v glavni program se vrnemo z druge vrstice. 1.4.3 Aritmetične operacije Ukaza: DECF F, D in INCF F, D Ta dva ukaza izvajata najpreprostejši aritmetični operaciji. Ukaz decf f, d (angl. decrement f ile register) zmanjša za 1 vrednost, ki se nahaja v podatkovnem pomnilniku na naslovu f. S parametrom d lahko določimo, ali se zmanjšana vrednost zapiše v podatkovni pomnilnik preko stare vrednosti (d = f ) ali v register W (d = w ). Ukaz incf f, d (angl. increment f ile register) počne isto, le da vrednost v podatkovnem pomnilniku poveča za 1. Pri obeh ukazih se nastavi indikator Z, v primeru, da je rezultirajoča vrednost enaka 0. Situacije, kjer moramo povečati ali zmanjšati vrednost določene spremenljivke za 1, so relativno pogoste, zato pozna večina mikroprocesorjev posebna

22 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP ukaza za ta namen, čeprav isti učinek dosežemo z ukazoma za seštevanje ali odštevanje, kjer je eden od operandov konstanta 1. Povečanje ali zmanjšanje vrednosti potrebujemo zlasti pri realizaciji vseh vrst števcev (štetje dogodkov, časovniki,...). Oglejmo si naslednji primer, kjer želimo realizirati programsko zanko, ki se trikrat ponovi. 1. movlw.3 2. movwf.37 3. zanka... 40. decf.37,f 41. btfss STATUS,Z 42. goto zanka Pred izvedbo zanke moramo inicializirati števec njenih izvršitev, da vemo, kdaj moramo prekiniti njeno izvajanje. Štetje lahko izvedemo na dva načina. (1) Števec ponovitev nastavimo na vrednost 0 in ga po vsaki izvršitvi zanke povečamo za 1. Nato testiramo, ali je njegova vrednost enaka želenemu številu ponovitev (v našem primeru 3). (2) Števec ponovitev nastavimo na želeno število ponovitev in ga po vsaki izvršitvi zanke zmanjšamo za 1. Nato testiramo, ali je njegova vrednost enaka 0. Pri izvedbi zank je druga izvedba pogostejša, saj je testiranje vrednosti 0 lažje: veliko ukazov nastavi indikator Z v primeru, da je rezultat operacije (npr. zmanjševanje za 1) enak 0. Zato lahko testiramo pogoj za izhod iz zanke (ali za njeno ponovitev) neposredno po zmanjšanju vrednosti števca izvršitev. Dodaten ukaz za primerjavo vrednosti števca ni potreben, s čimer prihranimo čas in programski pomnilnik. Poglejmo si dogajanje ob izvajanju gornjega programskega fragmenta. V prvi vrstici zapišemo želeno število ponovitev zanke (v našem primeru 3) v register W, da lahko v naslednji vrstici pravilno inicializiramo števec ponovitev, ki se v našem primeru nahaja na naslovu 37 10. V vrstici 3 se prične izvajanje zanke, ki jo lahko sestavlja poljubno število programskih ukazov, kar je na sliki simbolično označeno. Ob koncu zanke (vrstica 40) sledi zmanjšanje števca ponovitev za 1. Po prvem prehodu se njegova vrednost s 3 zmanjša na 2. Rezultat zmanjševanja ni 0, zato se indikator Z izbriše. Vrednost indikatorja testiramo v vrstici 41. Če je indikator Z nastavljen (kar v tem trenutku ni) preskočimo naslednji ukaz (kar se tokrat ne zgodi). Do preskoka ne pride in z ukazom goto skočimo na začetek zanke, s čimer se dogajanje ponovi. Po drugem prehodu skozi zanko se vrednost števca zmanjša z 2 na 1, kar še vedno ni enako nič, zato nas ukaz goto ponovno vrne na začetek zanke.

1.4. NABOR UKAZOV 23 Ko se zanka tretjič izvrši, se vrednost števca zmanjša z 1 na 0, kar povzroči, da se indikator Z nastavi. Testiranje njegove vrednosti v vrstici 41 povzroči preskok ukaza goto, zato se zanka ne ponovi več. Oglejmo si še primer uporabe ukaza incf. Tokrat želimo realizirati števec zunanjih dogodkov. Denimo, da štejemo avtomobile, ki prevozijo določen cestni odsek v enem mesecu. Tu nastane problem, ker je podatkovni pomnilnik 8-biten in vsaka pomnilniška lokacija lahko pomni samo številko med 0 in 255 (2 8 1). To niti slučajno ne zadostuje za štetje prometa, saj v enem mesecu lahko prevozi cesto stotisoč ali več vozil. Rešitev ponuja uporaba števca, ki se razširja preko večjega števila pomnilniških lokacij. Tak števec moramo realizirati sami (npr. z ustreznim podprogramom), saj ukaza incf in decf delujeta samo nad eno pomnilniško lokacijo. Naslednji fragment programa prikazuje, kako lahko realiziramo števec, ki zaseda tri pomnilniške lokacije oziroma 3 8 = 24 bitov. To omogoča štetje od 0 do 2 24 1 = 16.777.215, kar pri štetju avtomobilov na slovenskih cestah verjetno zadostuje. Števec implementiramo tako, da se nahaja na lokacijah 50, 51 in 52, kjer nižja lokacija vsebuje zlog z manjšo utežjo (angl. little endian counter). Ker so posamezni biti binarnega števca uteženi s potencami števila 2, so uteži po posameznih zlogih naslednje. Zlog 1: (2 0, 2 1,..., 2 7 ), zlog 2: (2 8, 2 9,..., 2 15 ) in zlog 3: (2 16, 2 17,..., 2 23 ). Vrednost števca izračunamo kot [50] + 256 [51] + 65536 [52], ker je utež prvega bita v drugem zlogu enaka 256 = 2 8, utež prvega bita v tretjem zlogu pa je 65536 = 2 16. 1. call vozilo 2.... 30. vozilo incf.50,f 31. btfss STATUS,Z 32. return 33. incf.51,f 34. btfss STATUS,Z 35. return 36. incf.52,f 37. return Dogajanje v programu je naslednje. Vrstica 1 simbolično nakazuje, da ob detekciji avtomobila pokličemo podprogram vozilo, ki mora poskrbeti za pravilno povečanje trizložnega števca. Podprogram se prične v vrstici 30. Najprej povečamo zlog števca z najnižjo utežjo. Če je vrednost zloga po povečavi enaka 0, je prišlo do prekoračitve. To se zgodi samo takrat, ko zlog

24 POGLAVJE 1. MIKROKRMILNIKI MICROCHIP pred povečavo vsebuje vrednost 255 10 = 1111 1111 2. Rezultat povečave bi moral biti enak 256 10 = 1 0000 0000 2, kar v 8 bitov ni možno zapisati. V pomnilnik se zapiše samo spodnjih 8 bitov rezultata, kar je 0 10 = 0000 0000 2, zaradi česar se indikator Z nastavi. Torej: pri ukazu incf se indikator Z nastavi ob povečanju vrednosti 255 za 1, kar zaradi prekoračitve 8-bitnega obsega vrne vrednost 0. V vrstici 31 testiramo, ali je do prekoračitve prišlo. Če temu ni tako, je povečanje števca opravljeno in z ukazom return se lahko vrnemo v glavni program. Primer: na začetku števec vsebuje vrednost 125 = 125 + 256 0 + 65536 0 ([50] = 125, [51] = 0, [52] = 0). Po izvedbi vrstice 30 števec vsebuje vrednost 126, ker do prekoračitve ni prišlo. Če prekoračitev nastane, kar pomeni, da je indikator Z nastavljen, se ukaz return v vrstici 32 izpusti in izvajanje podprograma se nadaljuje v vrstici 33. Tu izvedemo povečanje naslednjega zloga števca. Primer: na začetku števec vsebuje vrednost 255 = 255+256 0+65536 0 ([50] = 255, [51] = 0, [52] = 0). Po izvedbi vrstice 30 števec vsebuje vrednost 0 ([50] = 0, [51] = 0, [52] = 0). Poleg tega je indikator Z nastavljen, zato vemo, da proces povečanja vrednosti še ni končan. V vrstici 33 povečamo vsebino naslova 51, s čimer je vrednost števca enaka 256 = 0 + 256 1 + 65536 0 ([50] = 0, [51] = 1, [52] = 0). Pri tem povečanju ni prišlo do prekoračitve, zato se ukaz return v vrstici 35 ne preskoči, kar nas vrne v glavni program. Primer: števec na začetku vsebuje vrednost 2.031.615 = 255 + 256 255 + 65536 30 ([50] = 255, [51] = 255, [52] = 30). Povečanje v vrstici 30 povzroči prekoračitev ([50] = 0, [51] = 255, [52] = 30), zato nadaljujemo s povečevanjem. Povečanje v vrstici 33 zopet povzroči prekoračitev ([50] = 0, [51] = 0, [52] = 30), zato povečamo še tretji zlog števca, kar nas pripelje do rezultata 2.031.616 = 0 + 256 0 + 65536 31. Vidimo, da se povečanje števca s prikazanim podprogramom vedno pravilno izvrši. Ukaza: DECFSZ F, D in INCFSZ F, D Predhodna programska fragmenta sta nam demonstrirala uporabo ukazov decf in incf. Ugotovimo lahko, da obema ukazoma pogosto sledi ukaz, ki testira stanje indikatorja Z. Ukaza decfsz f, d (angl. decrement file register and skip if zero) in incfsz f, d (angl. increment f ile register and skip if zero) združujeta funkcijo pomanjšave/povečave s testiranjem indikatorja Z. V programu lahko zamenjamo zaporedje ukazov decf n, d in btfss STATUS,Z z ukazom decfsz n, d. S tem prihranimo programski pomnilnik in povečamo hitrost izvajanja programa. Dodatna ugodnost je, da ukaz decfsz ne vpliva na noben indikator, zato nam ne pokvari statusa morebitne predhodne aritmetične operacije.

1.4. NABOR UKAZOV 25 Na podlagi povedanega, zapišimo krajši, preglednejši in časovno učinkovitejši različici predhodnih dveh programskih fragmentov. Programsko zanko, ki se izvaja trikrat, realiziramo tako. 1. movlw.3 2. movwf.37 3. zanka... 40. decfsz.37,f 41. goto zanka Podprogram za povečanje trizložnega števca pa je naslednji. 1. call vozilo 2.... 30. vozilo incfsz.50,f 31. return 32. incfsz.51,f 33. return 34. incf.52,f 35. return Ukaza: ADDLW K in ADDWF F, D Kot pove že ime, izvajamo s tema ukazoma operacijo seštevanja. Ukaz addlw k (angl. add literal to W) prišteje 8-bitno konstanto k k vrednosti registra W in rezultat vpiše v register W. Primer: v registru W se nahaja vrednost 67 10. Po izvedbi ukaza addlw.20, bo register W vseboval vrednost 87 10. Ukaz addwf f, d (angl. add W to file register) sešteje vrednost v registru W z vrednostjo na naslovu f v podatkovnem pomnilniku. Kot smo že navajeni, s parametrom d določimo, ali se rezultat seštevanja zapiše v podatkovni pomnilnik preko stare vrednosti (d = f ) ali v register W (d = w ). Primer: v registru W se nahaja vrednost 23 10. V pomnilniku na naslovu 50 10 se nahaja vrednost 37 10. Po izvedbi ukaza addwf.50,f, se bo na naslov 50 10 vpisala vrednost 60 10. Če pa bi izvedli ukaz addwf.50,w, bi se vrednost 60 10 zapisala v register W, naslov 50 10 pa bi še naprej vseboval vrednost 23 10. Iz tabele 1.2 na strani 16 je razvidno, da seštevanje vpliva na vse tri indikatorje. Indikator Z se nastavi, ko je rezultat seštevanja enak 0, kar je pri nepredznačenih številih možno samo ob prekoračitvi obsega. Primer. Register W vsebuje vrednost 120 10. Po izvedbi ukaza addlw.136