Možda će vam se učiniti da lekcije obrađujemo na preskok i sa prevelikim iskoracima, ignorišući važno gradivo kao što su organizacija interne memorije mikrokontrolera ili set instrukcija, ali uskoro ćemo se i time baviti. Ovoga puta predstavljamo primer jednostavnog programa, tek da biste stekli utisak kako program izgleda i kakva je praktična svrha poznavanja interne arhitekture mikrokontrolera. Ništa nećemo preskočiti, ali pošto je materija ozbiljna, lakše ćemo je savladati ako je povremeno začinimo praktičnim primerima.
IDE i unos programa
| (kliknite za veću sliku) |
Mada je to u prethodnim tekstovima rečeno, nije na odmet ponoviti da će sve dosadašnje lekcije biti moguće pratiti samo uz korišćenje Microchip-ovog softverskog razvojnog okruženja MPLAB IDE, koji može besplatno da se preuzme sa www.microchip.com. Biće vam mnogo lakše ako ste ovaj program već instalirali i koliko-toliko se upoznali s njim.
IDE (Integrated Development Environment) je važna softverska alatka, ali je podjednako važno poznavati i mikrokontroler s kojim ćemo raditi. Stoga pretpostavljamo da ste već poštovali i drugi savet, da sa istog sajta i preuzmete PDF uputstvo za mikrokontroler PIC 18F1320. Deo tajne uspeha familije PIC mikrokontrolera leži u tome što je sve veoma dobro dokumentovano i što je na sajtu lako pronaći svaki podatak koji bi u konstruktorskom radu mogao da zatreba.
U radu ćemo se služiti isključivo asemblerom, jer je to kralj programskih jezika i temelj na kome su sagrađeni svi viši jezici. Osim toga, to je jedini jezik koji ima potpunu kontrolu nad registrima i najbliži je hardveru centralne jedinice procesora. Kasnije ćete pisati programe u nekom od viših jezika (C ili bejzik), ali ćete i tada neke delove morati da napišete u asembleru. Kada treba iscediti svaku kap procesorske snage, asembler je nezamenljiv.
Sada ćemo, dakle, zanemariti činjenicu da još ne poznajemo set instrukcija i konfiguraciju registara i krenućemo u analizu priloženog listinga. Ovaj program je napisan za projekat semafora, predstavljen u februarskom broju „PC“-ja, a radi upravo ono što je predstavljeno na „žutom“ blok-dijagramu iz martovskog broja: naizmenično pali i gasi zeleni LED u ritmu od jedne sekunde. Uskoro ćemo, liniju po liniju, videti kako on to radi.
Prošlog meseca ste pročitali da možete da koristite fajl u kome je početni okvir programa i koji se u našem slučaju zove 18F1320TEMP.ASM. Radi jednostavnosti i preglednosti, ovde ga nećemo u tom obliku koristiti, nego u obliku u kome ni njegov autor ne može da ga prepozna – program je preimenovan u SEMAFOR.ASM a iz njega je izbačeno je sve što je višak.
Pre nego što započnemo analizu, napomenućemo da je sav tekst koji je obojen zeleno zapravo vaš „privatni“ podsetnik. Ono što se iza svake linije nalazi iza znaka tačka-zarez (;) biće automatski obojeno u zeleno i to će asembler ignorisati, pa tu možemo da pišemo sve što mislimo da će nam kasnije koristiti. Ne treba štedeti prostor za komentare, jer kada program počne da raste i da se komplikuje, biće sve teže orijentisati se.
Konfiguraciju boja možete da podesite prema želji, kada desnim klikom odaberete Properties/Text. Pre početka rada korisno je da izvedete nekoliko podešavanja. Prođite slobodno kroz sve menije i upoznajte se s njima, a svakako otvorite Project/Build Options/Project/MPASM Assembler i štiklirajte polja Disable case sensitivity i Default Radix Decimal.
Najpre, niz direktiva
| (kliknite za veću sliku) |
Primetićete da najveći broj linija ne počinje od leve ivice, nego je za jedan tabulator uvučen udesno. Kada se budemo više bavili petljama, videćemo kako ovo „nazubljivanje“ može da doprinese većoj preglednosti programa, ali za sada je dovoljno reći da instrukcije moraju da budu odvojene od leve ivice – ako ne tabulatorom, onda bar jednim blankom. To je važno da bi asembler mogao da razlikuje instrukcije od definicija naziva simbola (ili labela) koji su uvek „zalepljeni“ za levu ivicu (takvih imamo ukupno šest u našem programu). I ovo nam značajno pomaže u orijentaciji, jer kada pratimo tok programa, veoma često pogledom tražimo mesto gde su definisani nazivi simbola.
U najvećem broju slučajeva postoji još jedan tabulator kojim je odvojena treća kolona. Tako imamo tri jasno odvojena niza: u prvom su definicije naziva simbola ili labele, u drugom su mnemonici i direktive (koji, najgrublje rečeno, određuju šta učiniti) a u trećem operandi, koji navode parametre, kojima se u najvećem broju slučajeva pokazuje gde to učiniti.
Prva linija u programu uvek definiše mikrokontroler s kojim radimo (list p=18f1320). To će pomoći asembleru u tumačenju sintakse instrukcija i u kontroli da li smo „izleteli“ van resursa koje taj mikrokontroler podržava, recimo, da li adresiramo neku nepostojeću memorijsku lokaciju.
Sledeća linija ponovo nije instrukcija, nego asemblerska direktiva (#include <p18f1320.inc>). Ona govori asembleru da celu datoteku p18f1320.inc postavi na to mesto u programu. Umesto ovoga, mogli smo i da „ručno“ iskopiramo datoteku, ali bi to učinilo program glomaznim i nepreglednim. Otvorite tu datoteku i videćete da u njoj postoje na stotine definicija koje samo nekim simbolima dodeljuju numeričke vrednosti, i to je sve. Recimo, registar PORTA (koji čini paralalni registar sastavljen od niza flip-flopova i tri-state bafera povezanih na pinove mikrokontrolera) nalazi se na internoj adresi 0F80 (izraženo u heksadecimalnom sistemu). Ovakvih registara ima na stotine, pa pošto ne bi bilo lako zapamtiti adrese za svaki od njih, mi ćemo umesto tih adresa koristiti nazive. S obzirom na to da u datoteci p18f1320.inc postoji i linija PORTA EQU H’0F80’, asembler će to zapamtiti kao „simbolički naziv PORTA je isto što i 0F80 heksadecimalno“... i tako za još nekoliko stotina simbola.
Naradnih pet linija će programator upotrebiti kako bi isprogramirao važan deo programske memorije, u kome su tzv. konfiguracioni registri. Ovih direktiva ima mnogo, ali mi ovde koristimo samo pet najvažnijih. U prvoj od njih se uključuje interni oscilator (tako da smo pošteđeni toga da gradimo spoljni generator takta), u sledećoj se isključuje mogućnost izbora tog nepostojećeg spoljnog oscilatora, zatim sledi linija kojom se isključuje watchdog (sigurnosni sklop koji budi procesor ako eventualno zaspi ili zaluta), pa direktiva koja isključuje funkciju eksternog RESET signala (i uključuje interni RESET) i, konačno, isključuje se mogućnost programiranja niskim naponom.
CBLOCK i ENDC su direktive kojima se određuje početak i kraj liste definicija u inernom RAM-u. To je RAM opšte namene, koji programer može da koristi po svom nahođenju – u svaku od 256 lokacija on može da upiše 8-bitnu vrednost i da je kasnije pročita sa istog mesta. Pošto smo iza CBLOCK stavili vrednost 0, asembler će listi simbola koje smo naveli redom dodeljivati vrednosti počev od 0. Mi ovde imamo samo dva simbola, OUTER i INNER, pa će prvi dobiti vrednost 0, a drugi 1.
Postoji i mogućnost da odvojimo više lokacija pod istim imenom, ako iza naziva simbola stavimo dvotačku i broj kojim određujemo veličinu memorije dodeljene tom simbolu. Recimo, da smo između prvog i drugog simbola napisali BUFFER: 20H, onda bi OUTER imao vrednost 0, BUFFER vrednost 1, a INNER bi imao heksadecimalnu vrednost 21.
Sve linije koje slede iza komentara „početak programa“ su instrukcije, sa izuzetkom prve i poslednje (i, naravno, labela koje nisu „nazubljene“). ORG je direktiva kojom određujemo od koje lokacije će se naredni program upisivati u programsku memoriju. Pošto posle RESET-a (koji se generiše automatski po uključenju napona) procesor uvek započinje izvršenje od adrese 0, najbolje će biti da pre prve instrukcije u programu napišemo ORG 0. Kasnije, ako poželimo da neki deo programa započne od nekog strogo određenog mesta, možemo ponovo da upotrebimo direktivu ORG, ali nikada tako da se upotrebljeni delovi programa preklapaju, jer će tada asembler prijaviti grešku.
Šta su instrukcije?
Instrukcije uvek sadrže jedan mnemonik i (najčešće) jedan ili više operanda. U prvoj instrukciji u programu mnemonik je MOVLW, što je skraćenica od MOVe Literal to Working register. Literal je bukvalna (neposredno naznačena) vrednost i ona je određena operandom, u našem slučaju b’01000010’ („b“ znači da je pod malim navodnicima binarna vrednost). Uskoro će biti jasno zašto je ovde zgodnije navesti vrednost u binarnom a ne u nekom drugom brojnom sistemu.
Kod mikrokontrolera PIC se glavni registar ne zove Akumulator, kao što je slučaj kod većine drugih procesora, nego Working register (često označen kao WREG), pa se ne obeležava slovom A nego W. To je prva specifičnost na koju se treba navići ako smo već radili s nekom drugom familijom procesora. Dakle, kada izvrši prvu instrukciju, naš mikrokontroler će u registru W imati binarnu vrednost 01000010 (u svakom brojnom sistemu se najpre ispisuje „najteža“ cifra, pa će ovde prva cifra predstavljati bit 7, a poslednja bit 0).
Sledeća instrukcija (linija 18) glasi MOVWF OSCCON. MOVWF je skraćenica od MOVe Wreg to File register. WREG znamo šta je (u njemu je već vrednost 01000010, spremna da se upiše u OSCCON), a File nije ništa drugo nego memorijska lokacija u internom RAM-u. Doduše, ne u RAM-u opšte namene (od koga smo mi iskoristili dva bajta i dali im imena OUTER i INNER), nego u RAM-u specijalne namene, koji nosi nazive koji su definisani u .INC datoteci i koje mi ne smemo da menjamo. Ako zavirimo u .INC datoteku, videćemo da se OSCCON nalazi na adresi 0FD3 heksadecimalno, što za nas nije ni od kakvog značaja, a ako pogledamo 17. stranu PDF priručnika, videćemo da se registar OSCCON sastoji od osam bitova, od kojih je svaki ponaosob za nas od velikog značaja.
Od kakvog značaja, pitaćete? E, to je domaći zadatak kojim možete da se bavite do sledećeg časa ove škole. Nije toliko važno da razumete značenje baš svakog bita, ali ćete svakako zapaziti kako smo isprogramirali oscilator da radi na taktu od 1 MHz (što ste verovatno već pročitali u komentaru linije u programu) i, što je još važnije, shvatićete kako se pomoću registara specijalne namene programira hardver mikrokontrolera. To je jedna od veoma važnih lekcija. Sa analizom programa ćemo nastaviti sledećeg meseca.
|