Funkcije u ARB 8051

U prošlom broju časopisa bio je predstavljen novi pri-stup u programiranju mikrokontrolera iz familije Intel 8051. Kratko podsećanje: uz pomoć standardnog C/C++ kompajlera stvaramo PC program čijim se izvršenjem generiše program za mikrokontroler, u odgovarajućem formatu. U ovom broju biće demonstrirane nove mogućnosti biblioteke ARB 8051, sa posebnim osvrtom na kreiranje funkcija.

Sa stanovišta programa za mikrokontroler funkcije u ARB imaju dvojako značenje:
a) funkcije kao potprogrami ili sekvence
b) funkcije kao makroi.
U prošlom broju, u primeru koji je dat, mogu se primetiti oba slučaja. U prvom, radi se o funkciji deklarisanoj kao void ImeFunkcije(void) koja sadrži telo potprograma. Izvršenje ovog potprograma se obavlja nakon njenog eksplicitnog pozivanja pomoću ARB funkcije

poziv(ImeFunkcije)(lcall), apoziv(ImeFunkcije) (acall).

Pored ovoga, funkcija može sadržati sekvencu koja se izvršava posle ARB funkcija kao što su

skok(reg Izraz,ImeFunkcije) ili skok(ImeFunkcije).

O ovoj upotrebi funkcija može se još puno govoriti,a ovoga puta biće više reči o drugom načinu korišćenja funkcija. Naime, ukoliko funkcija prima argumente ili vraća neku vrednost,tj. nije deklarisana kao
void ImeFunkcije(void), onda nije moguća njena upotreba kao potprograma ili sekvence već se u programu ona poziva bez ARB funkcija poziv() ili skok().
Neka je na primer data funkcija čija je deklaracija:

reg & min(reg pReg1,direct pReg2)

u programu ona može biti pozvana kao min(a,psw) ili r1=min(r2,lok) ili min(r0,tmod)+r3 , pa i ImeBloka.opet(min(r5,acc)).

Gledano sa strane programa za mikrokontroler, telo ove funkcije se umeće u program gde god ta funkcija bude pozvana. Stoga se ovde može govoriti o primeni funkcije kao makroa jer nema uštede u veličini koda ali se zato dobija na brzini i vrlo fleksibilnoj primeni. Pre nego što bude prikazan kod za funkciju min() predstavićemo jednu malu ali korisnu funkciju čija je svrha komparacija vrednosti dva registra (Listing1). Izvršenjem linije temp.napusti(pReg1!=pReg2) (odnosno cjne pReg1,pReg2,izlaz) vrši se postavljanje bita c u zavisnosti da li je pReg1 manji ili veći od pReg2. Zbog toga ova funkcija vraća objekat tipa flag, tačnije c. Zahvaljujući tome, funkciju je moguće primenjivati u izrazima gde god se javlja varijabla tipa flag. Evo kako to izgleda u već pomenutoj funkciji min() (Listing 2)
Izvršenjem funkcije min() minimalna vrednost registara, koji se kao argumenti njoj predaju, biva dodeljena akumulatoru koji se u ovom slučaju koristi kao povratna vrednost. Za bolje razumevanje ove funkcije svakako će pomoći komentari u obliku asemblerskog koda. U zavisnosti od ishoda izvršenja funkcije comp(a,pReg2) biće dodeljivanje manje vrednosti akumulatoru: ukoliko je c setovan (a<pReg2) minimalna vrednost je već u akumulatoru,u suprotnom a=pReg2.
Ova dva kratka primera donekle ilustruju interesantne mogućnosti ARB 8051 programske podrške. Naš sledeći primer funkcija set_dptr() će osim toga pokazati mesto i smisao C naredbi u ARB sintaksi. Registru dptr (Data Pointer) je moguće neposredno dodeliti vrednost instrukcijom dptr=podatak; (mov dptr,#podatak), ali u nekim situacijama je poželjno postavljati vrednost registra dptr relativno, u odnosu na neku referentnu vrednost. Evo kako je to realizovano u primeru na listingu br. 3.
Veličina pomeraja se zadaje preko celobrojnog argumenta ‘pomer’. Ukoliko je njegova vrednost pozitivna onda se ispituje da li je jednaka jedinici kako bi se razdvojilo inkrementiranje dptr (inc dptr) od dptr+pomer (ne postoji takva instrukcija u setu naredbi). Ukoliko je, medjutim, vrednost argumenta negativna vrši se njegova negacija i prelazi na sekvencu dptr-pomer. Naredbe if i else u ovom slučaju, treba shvatiti analogno pretprocesorskim direktivama u programskom jeziku C. To praktično znači da se nijednom C naredbom za kontrolu izvršenja programa ne može kontrolisati tok izvršenja programa za mikrokontroler (za ovu namenu se koriste ARB funkcije pridružene klasi blok), već se njima može kontrolisati proces generisanja koda za mikrokontroler kao što je to uradjeno u primeru funkcije set_dptr(). U glavnom programu ova funkcija može biti pozvana na sledeće načine:
set_dptr(5); // dptr+5
set_dptr(1); // inc dptr ili
set_dptr(-3); // dptr-3.
U sva tri slučaja u program biva umetnut različit kod, u zavisnosti od vrednosti argumenta koji se predaje funkciji.
U jednom od prošlih brojeva časopisa “Mikroelektronika” bilo je reči o tzv. look_up tabelama odnosno nizu uzastopnih memorijskih lokacija koje sadrže unapred zadate konstantne vrednosti i koji zauzima odredjeni prostor programske memorije. Naša sledeća funkcija upravo radi sa jednom takvom tabelom i pokazuje prednosti metoda ARB programiranja.
}
blok x(LOOK_UP);
for(int i=0;i<=90;i++)
db((int)100*sin(PI*i/180));
{
Najpre formiramo tabelu korišćenjem ARB 8051 funkcije db(int). Umesto da svakoj memorijskoj lokaciji dodeljujemo vrednost, pozivamo u pomoć jednu for-petlju kojom se look_up tabela ispunjava odgovarajućim vrednostima. Tabela zauzima 91 (a ne 181) bajt čime se štedi na prostoru. Funkcija sinus() vraća normalizovanu vrednost sinusa ugla od 0 do 180 stepeni. Ako se ovoj funkciji preda veća celobrojna vrednost od 180, ispisuje se poruka o grešci i uvećava varijabla LB.gr za jedan (ova promenljiva sadrži broj grešaka u programu: videti datoteku arb8051.h) kako se bi se izbeglo forniranje koda. Ukoliko je medjutim ova vrednost u ispravnom opsegu onda se ispituje u kom kvadrantu se nalazi zadati ugao. Zahvaljujući jednakosti sin(x)=sin(180-x) za ugao u intervalu 0 do 180, nije potrebno formirati tabelu za uglove od 0 do 180 stepeni već samo za uglove od 0 do 90 stepeni. Ostatak funkcije biće razumljiv ako se pogledaju komentari (Listing4).

U programu ova funkcija može biti pozivana samostalno ili pridružena izrazima gde figuriše varijabla a kao na primer:

r2=sinus(30);
r3=sinus(60)+r1;

U nekom od sledećih nastavaka biće predstavljena ista funkcija sa promenljivom tipa reg kao predajnim parametrom koja bi u mnogim situacijama bila korisnija nego funkcija sa celobrojnim argumentom.

Autor: Dragan Golubović