Sunteți pe pagina 1din 9

3.

Structuri de program


Pentru a realiza programe scalabile i lizibile, codul i datele trebuie grupate.
Macrourile i subrutinele joac un rol important n gruparea codului, datele fiind grupate
n structuri denumite tablouri.

3.1 Macrouri i subrutine.
Structurarea codului folosind macrouri i subrutine reprezint o practic bun de
programare, aceste structuri formnd baza unor limbaje consacrate precum C i
Pascal. n limbaje de asamblare, funciile nu sunt att de vizibile precum n limbajele
amintite ns numai prin stpnirea acestor structuri se vor putea dezvolta programe
scalabile.

3.1.1 Macrouri.
n limbajul C, macrourile (cunoscute i sub denumirea de macrodefiniii sau
macroinstruciuni) sunt definiii care nlocuiesc constante, variabile sau expresii, fiind
declarate cu ajutorul directivei #define. n cadrul asamblorului considerat, macrourile
sunt secvene de instruciuni care nlocuiesc un apel al macroului.
Sintaxa de definire a unui macro:
etichet macro [arg1, arg2, ]
[instruciune 1]
[instruciune 2]
[]
endm

Exemplul 3.1. Definirea unui macro de stocare a dou valori val1 i val2
parametrice la locaiile de memorie avnd adresele respectiv 0 i 15.

ram_0 EQU d0 ;Constanta asamblor cu valoarea 0
ram_15 EQU 0x0F ;Constanta asamblor cu valoarea 15

;Definire macro Stocare
Stocare macro val1, val2
MOVLW val1
MOVWF ram_0 ;Adresa RAM 0
MOVLW val2
MOVWF ram_15 ;Adresa RAM 15
endm

;Apelul macroului
Stocare h3F, hF0

Ceea ce este specific macrourilor este faptul c fiecare apel al acestora echivaleaz
cu o inserare a setului de instruciuni din corpul macroului la adresa de apel. Folosirea
acestor structuri se preteaz de regul n situaii n care acestea nu conin multe
instruciuni i integrarea altor structuri (cum ar fi cele cu salt) ar duce la o scdere a
performanelor sistemului.
Macrourile ofer o claritate n plus programelor ntruct chiar i simple seturi de
instruciuni pot fi nlocuite cu o expresie familiar programatorului. Un asemenea
exemplu este construcia din exemplul 2.

Exemplul 3.2. Macro pentru selectarea BANK-ului 2 de memorie.

;Definire macro BANK2
BANK2 macro
MOVLW 0x02 ;Selectarea bank-ului dorit se face
MOVWF BSR ;prin stocarea valorii corespunztoare
endm ;n registrul special BSR

;Apelul macroului
BANK2

Exemplul 3.3. Definirea unui macro de adunare a dou numere folosind o locatie de
memorie temporar situat la adresa 0. Rezultatul se va stoca n registrul de lucru w.

ram_temp EQU 0x00

;Definire macro Adunare
Adunare macro val1, val2
MOVLW val1
MOVWF ram_temp
MOVLW val2
ADDWF ram_temp, 0
endm

;Apelul macroului
Adunare 0x23, 0x43

Avantaje:
Claritatea codului la scriere prin posibilitatea redenumirii unor seturi de
instruciuni folosind expresii familiare programatorului.
Reducerea dimensiunii codului la scriere prin definirea unui macro pentru
seturi de instruciuni care se repet.
Eficien ridicat la execuia setului de instruciuni inclus n macro ntruct
acestea sunt inserate n cod la compilare, nemaifiind necesar efectuarea
unui salt.
Dezavantaje:
Pot introduce erori subtile de programare cum ar fi modificarea unor zone
de memorie nedorite datorate ignorrii coninutului macroului (poate apare
cu uurin n cadrul unor proiecte mari unde se folosesc macrouri scrise de
alte persoane).
Creterea n dimensiuni a codului compilat prin folosirea unor apeluri de
macro de multe ori. Aceast problem este deosebit de suprtoare n cazul
n care se folosesc macrouri foarte mari (de exemplu, pentru realizarea unei
ntrzieri de 100 microsecunde la 20 Mhz trebuie incluse 500 de instruciuni
NOP).

3.1.2 Subrutine.
Pentru a executa aceleai instruciuni de mai multe ori fr a recurge la reinserarea
codului, se pot folosi subrutine. n limbajul C subrutinele se regsesc sub forma unor
funcii, avnd un nume, tip returnat i un set de parametrii. n cadrul limbajelor de
asamblare, subrutinele iau forma unor etichete opionale i instruciuni de revenire la o
adres de salt.
Sintaxa de definire a unei subrutine:
[etichet:]
[instruciune 1]
[instruciune 2]
[]
RETURN | RETLW | RETFIE

Exemplul 3.4. Subrutin de setare PORTC , n comentariile aferente fiind precizate
i adresele instruciunilor.

GOTO Main ;0000 Salt peste subrutin

Setare_Port:
MOVLW 0xF0 ;0004
MOVWF TRISC ;0006
RETURN ;0008 Revenire din subrutin

Main:
CALL Setare_Port ;000A Apelul subrutinei

Instruciunea de apel al unei subrutine este CALL, urmat de o etichet
reprezentnd adresa la care se face salt. n exemplul anterior, adresa la care se afl
eticheta Setare_Port este 0004, adic adresa primei instruciuni din subrutin.
Pentru ca la apelul unei subrutine microprocesorul s poat realiza un salt la o
anumit adres unde s execute un set de instruciuni, trebuie s se parcurg urmtorii
pai:
(1) Se salveaz pe stiv adresa de revenire (valoarea numrtorului de program)
STACK.push(PC)
(2) Se ncarc n numrtorul de program adresa etichetei
Adresa(etichet) PC
(3) Se execut instruciunile din subrutin.
Prin paii enumerai se salveaz adresa de revenire pe stiv iar saltul la adresa
indicat de etichet echivaleaz de fapt cu o ncrcare a unei adrese n numrtorul de
program.
Aceti pai fac parte din execuia unei instruciuni CALL, iar din cauza saltului,
timpul de execuie este de dou ori mai mare dect al unor instruciuni simple de
manipulare a regitrilor (cum ar fi MOVLW, MOVWF, etc.).
Revenirea dintr-o subrutin se face la ntlnirea unei instruciuni RETURN sau
RETLW. Pentru revenirea dintr-o rutin de tratare a unei ntreruperi se execut o
instruciune RETFIE (despre aceast instruciune se va vorbi mai mult n cadrul
laboratorului de ntreruperi). Paii executai:
(1) Se stocheaz n numrtorul de program vrful stivei (care la o execuie
corect este de fapt adresa de revenire salvat)
STACK.pop() PC
(2) Se execut instruciunile existente dup CALL

Avantaje:
Ca i n cazul folosirii macrourilor, includerea unor subrutine n cod poate
duce la o cretere a claritii programului.
Subrutinele sunt des folosite la distribuirea codului ntr-o echip ce include
mai muli programatori, mpreun cu macrourile fcnd posibil
modularizarea.
ns cel mai important avantaj l constituie posibilitatea execuiei aceleiai
secvene de cod din puncte diferite de program folosind salturi fr re-
includerea codului, aa cum este cazul macrourilor.
Dezavantaje:
Datorit saltului efectuat la adresa de nceput a subrutinei i saltului de
revenire, va rezulta un timp de execuie mai mare.


3.2 Tablouri.
Pentru gruparea datelor n structuri denumite tablouri, se poate folosi una din
metodele urmtoare: instruciuni microprocesor, adresarea indirect, instruciuni
tabelare.


3.2.1 Implementarea tablourilor folosind instruciuni microprocesor.
Aceast metod presupune stocarea valorilor tabloului n memoria program, fiind
folosit n deosebi n situaiile n care valorile respective nu se doresc a fi modificate. Cu
toate c valorile tabloului nu se pot modifica
1
, acest metod are avantajul c permite
stocarea unui numr mult mai mare de valori dect ar fi posibil prin folosirea RAM-ului.
Fiindc se folosesc instruciuni microprocesor n realizarea tablourilor,
programatorul poate implementa o rutin de accesare a valorilor dup bunul su plac. O
metod foarte popular care poate fi folosit att la seria 16F ct i la seria 18F (se poate
folosi de fapt la toate microcontrollere care permit manipularea numrtorului de
program) implic instruciuni de manipulare a numrtorului de program i instruciunea
RETLW.

Exemplul 3.5. Rutin de simulare al unui tablou cu 8 elemente aleatoare. Accesul la
valori se realizeaz indexat folosind ca variabil index, registrul de lucru W.

;Rutin de simulare al unui tablou pentru microcontrollere ;PIC cu
instruciuni RETLW pe 2 octei (18Fxxxx) (a) i pe 1 ;octet (16Fxxxx)
(b)

1
Modificarea memoriei program prin intermediul unui program este posibil doar dac exist instruciuni
speciale. Altfel, aceast modificare se poate realiza doar printr folosirea unui circuit extern, fapt care
echivaleaz cu inscripionarea microcontrollerului. Aceste instruciuni speciale fac parte din setul de
instruciuni normale la microcontrollere PIC din seria 18Fxxxx.

Tabela_Test:
MULLW D'2'
MOVF PRODL, W
MOVFF PCL, 0x00
ADDWF PCL, F
RETLW D101
RETLW D115
RETLW D90
RETLW D83
RETLW D85
RETLW D99
RETLW D150
RETLW D149


(a)
Tabela_Test:
MOVWF 0X20
MOVLW high $
MOVWF PCLATH
MOVF 0X20, W
ADDWF PCL, F
RETLW D101
RETLW D115
RETLW D90
RETLW D83
RETLW D85
RETLW D99
RETLW D150
RETLW D149

(b)


;Accesarea valorii cu index-ul 3 (valorile indecilor pornesc de la 0)
MOVLW D3
CALL Tabela_Test
;n acest moment, n registrul W se afl valoarea D83

n exemplul 3.5 se poate observa faptul c deoarece ntregul tablou reprezint de
fapt un set de instruciuni, acesta va fi stocat n memoria program la inscripionarea
microcontrollerului. n cazul rutinei (a), prezena instruciunii de multiplicare este
justificat de numrul de octei alocai reprezentrii instruciunii RETLW. Astfel, pentru a
returna o valoare de la un anumit index, mai nti trebuie nmulit index-ul respectiv cu 2
(rezultatul fiind stocat n PRODL:PRODH) dup care rezultatul este adunat la numrtorul
de program, astfel, instruciunea care va fi executat dup ADDWF PCL, F va avea
adresa:
Adres_Instr_Urmtoare = $ + INDEX * 2,
unde $ reprezint adresa instruciunii curente (ADDWF PCL, F).
n acelai exemplu, instruciunea MOVFF PCL, 0x00 stocheaz valoarea
inferioar a numrtorului de program la adresa RAM 0x00. Prezena acestei instruciuni
se justific prin problemele pe care le introduce structura numrtorului de program pe 21
de bii.
Astfel, cei 21 de bii sunt mprii n 3 regitrii: PCL, PCH i PCU. Dintre acetia,
doar PCL se poate citi i scrie direct. Pentru PCH i PCU s-au introdus doi regitrii
imagine: PCLATH i PCLATU. Astfel, valorile reale din PCH i PCU se transfer n
PCLATH respectiv PCLATU numai la o citire a registrului PCL (CALL, GOTO sau citire
direct prin instruciuni). Dac se modific valoarea PCL-ului, atunci valorile care se afl
n PCLATH i PCLATU sunt transferate respectiv n PCH i PCU.





PCU PCH PCL
20 16 15 8 7 0


PCLATU PCLATH

Figura 3.1. Structura numrtorului de program pentru PIC18Fxxxx

n cazul rutinei (b), indexul tabloului se stocheaz mai nti ntr-o variabil
temporar situat la adresa 0x20. La fel ca i n cazul punctului (a), pentru a face un salt
la un anumit index din tablou, mai nti trebuie stocat o valoare pentru PCLATH, pentru
ca la modificarea registrului PCL, PCH s fie ncrcat cu o valoare corespunztoare.


PCH PCL


PCLATH

Figura 3.2. Structura numrtorului de program pentru PIC16Fxxxx

3.2.2 Implementarea tablourilor folosind adresarea indirect.
Adresarea indirect ofer posibilitatea accesrii unei locaii de memorie RAM fr
precizarea unei adrese fixe n instruciune. Astfel, dac se implementeaz tablourile
folosind aceast metod, se vor putea stoca valori modificabile pe parcursul execuiei
programului (prin folosirea RAM-ului ca i zon de stocare).
Microcontrollerele PIC fac posibil adresarea indirect prin implementarea unui set
de regitrii speciali de selecie a adresei de memorie, denumii File Select Registers
(FSR) (vezi capitolul Organizarea memoriei).

Exemplul 3.6. Implementarea unui tablou de 8 elemente folosind adresarea
indirect.

;Rutin de stocare a valorilor care vor fi accesate ulterior
;prin rutina de returnare a unei valori
Stocare_Valori:
LFSR FSR0, H200 ;Bank-ul 2 (cu numrul 3)
MOVLW D101
MOVWF POSTINC0 ;Stocarea valoarii i imcrementarea
MOVLW D115 ;automat a registrului FSR0
MOVWF POSTINC0
MOVLW D90
MOVWF POSTINC0
MOVLW D83
MOVWF POSTINC0
MOVLW D85
MOVWF POSTINC0
MOVLW D99
MOVWF POSTINC0
MOVLW D150
MOVWF POSTINC0
MOVLW D149
1 1
2 2
1 Citire PCL
2 Scriere PCL
1
1 Scriere PCL
12 8 7 0
MOVWF POSTINC0
RETURN

;Rutin de returnare a valorii avnd indexul stocat n
;registrul de lucru
Ret_Valoare:
LFSR FSR1, H200 ;Se poate folosi i FSR0
MOVWF FSR1L
MOVF INDF1, W
RETURN

Astfel, pentru a putea folosi tablouri implementate prin adresarea indirect, valorile
tabloului trebuie s fie ncrcate mai nti n memoria RAM. Aceasta se poate realiza sub
forma unei rutine de iniializare a memoriei, precum n exemplul 3.6.


3.2.3 Implementarea tablourilor folosind instruciuni dedicate (valabile doar
pentru seria 18Fxxxx).
O alt variant de implementare a tablourilor n memoria program o reprezint
folosirea instruciunilor tabelare oferite de microcontrollerele din seria 18F. Acestea ofer
posibilitatea citirii memoriei program octet cu octet i scrierea acesteia prin blocuri de
minim 32 de octei. Instruciunile folosite pentru citire/scriere:
Citire tabelar: TBLRD
Scriere tabelar: TBLWT
Registrul folosit pentru adresare este TBLPTR, un registru pe 22 de bii, prezentat
n figura 3.3.


Figura 3.3 Structura registrului TBLPTR

Astfel, pentru adresarea unei locaii de memorie FLASH, se vor folosi cele trei
componente ale registrului special TBLPTR (TBLPTRU:TBLPTRH:TBLPTRL). Aceti
regitrii sunt folosii de instruciunile TBLRD i TBLWT pentru adresarea unei zone de
memorie, instruciuni care ofer i posibilitatea modificrii automate a regitrilor adres
(printr-o singur instruciune).

Instruciunea Operaia executat
TBLRD*
TBLWT*
Se realizeaz o citire/scriere;
TBLPTR nu se modific
TBLRD*+ Se realizeaz o citire/scriere;
TBLWT*+
TBLPTR este incrementat
TBLRD*-
TBLWT*-
Se realizeaz o citire/scriere;
TBLPTR este decrementat
TBLRD+*
TBLWT+*
TBLPTR este incrementat;
Se realizeaz o citire/scriere
Tabelul 3.1 Parametrii instruciunilor TBLRD i TBLWT

Zona de memorie n care se transfer un octet la execuia unei instruciuni de citire
este un registru special pe 8 bii: TABLAT. Formele instruciunilor de manipulare a
memorie FLASH sunt prezentate n Tabelul 3.1.
Pentru stocarea unui ir de valori n memoria program se pot folosi fie instruciuni
ale cror coduri sunt bine cunoscute de programator i sunt astfel strategic plasate n
program, fie prin definirea unei secvene de octei folosind operatorul db, precum n
exemplul 3.7.

Exemplul 3.7. Stocarea unei secvene de octei n memoria program i citirea
acesteia folosind instruciuni TBLRD.

Tablou_valori:
db 0x12, 0x13, 0x90, 0x20, 0x18, 0x23, 0x11, 0x55

;Rutin de iniializare a regitrilor de adresare
;unde: -low instruciune adresat asamblorului
; pentru determinarea prii inferioare a adresei la
; care se afl eticheta Tablou_valori (i.e. adresa
; primului element din tablou)
; - high determinarea prii superioare ...
; - upper - determinarea prii de sus ...
Init_Adresa:
MOVLW low Tablou_valori
MOVWF TBLPTRL
MOVLW high Tablou_valori
MOVWF TBLPTRH
MOVLW upper Tablou_valori
MOVWF TBLPTRU
RETURN

;Mai nti se apeleaz rutina de iniializare
CALL Init_Adresa

;Dup care se pot accesa elementele pe rnd folosind ;postincrementarea
TBLRD*+
MOVF TABLAT, W

;Sau se poate accesa un element de la un anumit index
;ns dac se modific manual valorile din regitrii de ;adres
trebuie avut grij la depirea valorii 255, cnd ;trebuie modificat i
registrul imediat superior
MOVLW D3 ;se va returna elementul cu index-ul 3
MOVWF TBLPTRL
TBLRD*
MOVF TABLAT, W

Iniializarea regitrilor de adresare i citirea unei zone de memorie FLASH este
ilustrat n exemplul 3.7. Realizarea unei modificri a memoriei program (i.e. scrierea
memoriei FLASH) folosind instruciuni TBLRD i TBLWT este puin mai complex,
cuprinznd operaii asupra EEPROM-ului i instruciuni de iniializare bine stabilite.
Prin aceste instruciuni, utilizatorul poate construi aplicaii tip Boot-loader sau
poate implementa tablouri modificabile ale cror dimensiune limit este stabilit doar de
dimensiunea memoriei program. Pentru mai multe informaii legate de scrierea memorie
program, se poate consulta site-ul www.microchip.com sau exemplul prezentat n
ANEXA 1.


Probleme.
P1. Se consider 20 de valori stocate sub forma unui tablou (implementarea tabloului se
consider a fi la alegere) i 8 LED-uri legate la PORTC. S se afieze valorile stocate n
tabel pe PORTC.

P2. Se consider 8 LED-uri legate la PORTC. S se afieze pe portul considerat octeii
din memoria program folosind instruciuni tabelare (metoda numrul 3). Pentru a putea
observa valorile afiate, se va folosi un timer pe 8 sau 16 bii.