Sunteți pe pagina 1din 13

Ministerul Educaiei al Republicii Moldova

Universitatea Tehnica a Moldovei


Facultatea CIM
Catedra Microelectronica i Ingineria Biomedical


Raport
La Microprocesoare
Lucrare de laborator Nr. 2
Tema: Subrutinele




A elaborat: Cvasniuc Ivan

A verificat: Bragarenco Andrei




Chiinu 2012

1) Scopul lucrrii: utilizarea subrutinelor n realizarea programelor cu limbajul ASM.

2) Expunerea problemei: n cadrul acestui laborator ne propunem sa realizm un program cu
ajutorul AVR Studio care ar permite deplasarea luminilor prin LED-uri. Vom folosi cele patru
porturi a microcontrollerului. Astfel n total vom avea 32 de LED-uri.

3) Generaliti:
Contorul comenzilor
Contorul comenzilor reprezint un registru, n care se afl adresa urmtoarei comenzi care
trebuie efectuat. Utilizatorul nu are acces direct la contor. Mrimea contorului depinde de
volumul PM (Program memory) (12 bii ATMega8x, 16 bii ATMega128x).
La ndeplinirea normal a programului coninutul contorului se mrete cu 1 sau 2 la fiecare
impuls de tact. Aceast rnduire este nclcat la ndeplinirea instruciunelor de salt, de
chemare, la returnarea din subrutine sau la ntreruperi.
La conectarea alimentaiei, sau la resetarea MCU n contor automat se incarc adresa de
start $0000.
Funcionarea conveerului
n MCU familiei AVR Mega pentru prelucrarea comenzilor se folosete principul de
conveerizare (Fig. 1.1).

Fig. 1.1

n timpul primului impuls de tact se produce alegerea instruciunii din PM i decodarea ei. La
al doilea impuls instruciunea se prelucreaz, iar paralel se produce alegerea i decodarea
instruciunii urmtoare .a.m.d.
n realitate la prelucrarea unui ir de instruciuni funcionarea normal al conveerului va fi
nclcat. Aceasta poate fi condiionat de instruciunele de salturi condiionate, i de comenzile
de tip Test & Skip. n caz de rezultat pozitiv, ndeplinirea programului va fi nevoit s continue
de la o adres anumit (conform instruciunii). Dar din cauza c n conveer deacuma sa
ndeplinit alegerea, timpul de ndeplinire a instruciunii de salt se va mri cu un impuls de tact,
n timpul cruia se va produce alegerea instruciunii care se afl la adresa necesar.
Instruciuni de tip Test & Skip
n instruciunele de acest tip se produce verificarea unei condiii, rezultatul creia
influeneaz ndeplinirea urmtoarei instruciuni. Dac rezultatul este pozitiv, urmtoarea
instruciune se ignoreaz. De exemplu instruciunea SBRS Rd, b verific bitul b din registrul de
uz general Rd i ignoreaz urmtoarea instruciune, dac bitul are valoarea 1. La rezultatul
pozitiv n conveer se produce o ntrziere, care este legat de necesitatea ncrcrii i decodrii
instruciunii noi. Durata ntrzierei depinde de mrimea instruciunii care a fost neglijat (de la
1 pn la 3 impulsuri de tact).
Instruciunele saltului condiionat
n aceste instruciuni se produce verificarea condiiei, rezultatul influeneaz la starea
contorului. Dac rezultaul este pozitiv, se produce trecerea la adresa indicat, dac rezultatul
este negativ se execut instruciunea urmtoare.
Instruciunele de salt condiionat au restricii n domeniul de lucru. n realitate valoarea nou
a contorului al contorului se primete prin adugarea sau scderea din el a unei treceri. Pentru
treceri sunt rezervai 7 bii, astfel trecerea maxim poate fi de -63...+64 de cuvinte.
Instruciunele saltului necondiionat
Sunt 3 instruciuni de salt necondiionat: instruciunea de salt relativ RJMP, salt absolut JMP
i instruciunea de salt indirect IJMP.
Instruciunea RJMP la ndeplinirea instruciunii, coninutul contorului se modific prin
adugarea sau scderea a unei valori, care reprezint operandul instruciunii, cum este artat n
fig. 1.2. Poziia biilor k pe figur sunt artate condiionat. ntruct sub valoarea operandului n
cuvntul instruciunii se rezerv doar 11 bii, cu ajutorul acestei instruciuni este posibil
trecerea numai n intervalul de -2047...+2048 cuvinte.

Fig. 1.2

n programe n calitate de operatori al acestei comenzi se folosesc etichetele. Mrimea
transportului se calculeaz de ctre assembler. Deoarece instruciunea saltului relativ schimb
starea contorului, ea se efectueaz n 2 impulsuri de tact.
Salt absolut instruciunea JMP
La ndeplinirea instruciunii JMP n contor se ncarc valoarea adresei, care este operadnul
(Fig. 1.3). Cu ajutorul acestei instruciuni este posibil trecerea la tot spaiul de adresare.

Fig. 1.3

Instruciunea JMP se ndeplinete timp de 3 impulsuri de tact.
Salt indirect instruciunea IJMP
La ndeplinirea acestei instruciuni se efectueaz trecerea la adresa indicat nregistrul de
index Z. Astfel procesul se reduce la ncrcarea coninutului din Z n contor (Fig. 1.4).
Ca i instruciunea de salt aboslut, instruciunea dat nu are restricii n spaiul de adresare.
Deoarece registrul Z este constituit din 16 bii, saltul maximal este de 128 Kb, anume aa volum
are PM n modelele Atmega128x. Instruciunea IJMP se ndeplinete timp de 2 impulsuri de tact.


Fig. 1.4

Instruciunele de apel a subrutinelor
Exist 3 instruciuni de apel a subrutinelor: apelul relativ RCALL, apel absolut CALL, apel
indirect ICALL.
RCALL inainte de toate instruciunea RCALL salveaz n Stack valoarea contorului. Apoi
aceast valoare se incrementeaz sau se decrementeaz cu o valoarea anumit, indicat prin
operand (Fig. 1.2). ntruct operandul conine 12 bii, tranziia maxim va fi 2047...+2048.
n calitate de operanzi se folosesc etichetele, iar assembler-ul singur calculeaz valoarea de
tranziie. Instruciunea RJMP se efectueaz timp de 2 impulsuri de tact, 2 din care se cheltuie
pentru salvarea n stack.
CALL La ndeplinirea instruciunii dup salvarea n stack al valorii curente a contorului n
ultimul se ncarc un numr, care este operandul. Cu ajutorul acestei instruciuni se poate
efectua apelul din tot spaiul de adresare. Instruciunea se ndeplinete timp de 4 impulsuri de
tact.
ICALL instruciunea salveaz n stack valoarea contorului, apoi ncarc coninutul
registrului de index. Valoarea maxim a tranziiei este de 128 Kbaii. Instruciunea se
efectueaz timp de 3 impulsuri de tact.
Instruciunele de revenire din subrutine
La sfritul subrutinei neaprat trebuie s existe instruciunea de revenire. Exist 2
instruciuni de acest tip. Pentru revenirea din subrutina simpl cu ajutorul instruciunii RET,
care se apeleaz cu instruciunea RCALL. La rentoarcerea din subrutin pentru prelucrarea
ntreruperilor se folosete instruciunea RETI.
Ambele instruciuni restabilesc din stack coninutul contorului, care a fost salvat acolo
nainte de apel. Instruciunea RETI instaleaz suplimentar n 1 flagul de ntreruperi I al
registrului de stare SREG. Pentru indeplinirea instruciunilor de revenire se cheltuie 4
impulsuri de tact.
STACK
Pentru a putea folosi rutinele in codul nostru trebuie mai intai sa initializam stiva. Aceasta
este tinuta in memoria SRAM a MCU si este incrementata de la jos in sus, de la ultima adresa
catre prima. Initializarea stivei consta in initializarea registrului Stack Pointer (SP) cu o adresa
de start, la care se va introduce primul element. In cod, acest lucru este realizat de secventa
urmatoare:
ldi r16, HIGH(RAMEND) ; Octetul HIGH al adresei stivei
out SPH, r16
ldi r16, LOW(RAMEND) ; Octetul LOW al adresei stivei
out SPL, r16
Constanta RAMEND are valoarea 0x045F si reprezinta ultima adresa din memoria RAM de
1kB a C. Registrul SP este impartit in doua registre de cate opt biti, SPL si SPH care vor primi la
initializare octetul low, respectiv high din RAMEND. La orice operatie de introducere in stiva
(push), registrul SP va fi decrementat, iar la fiecare operatie de extragere din stiva (pop) SP va fi
incrementat.
De exemplu instructiunea call pattern1 va salva in stiva adresa urmatoare din memoria de
program apoi va executa instructiunile din corpul rutinei pattern1. In momentul intalnirii
instructiunii ret programul extrage din stiva adresa salvata si se intoarce in programul principal
la instructiunea urmatoare
Mersul lucrrii
1. Conform sarcinii propuse se cosntruiete schema electric de funcionare (fig.1) :



Fig. 1



2. Conform schemei date cosntruim schema bloc a programului (Fig. 2):
Astfel prin utilizarea subrutinelor problemele mai complexe se reduc la alte probleme mai simple.
Pentru cazul dat avem de rezolvat 3 probleme simple:
I. Init_Lights iniializarea registrilor periferici DDRx i PORTx pentru configurarea LED-urilor.
Registrii periferici DDRx vor fi setai la intrare, iar PORTx conform parametrilor de intrare.
Subrutina va conine 4 parametri de intrare 4 registri de uz general R16, R17, R18, R19, care
vor conine informaie despre configurarea ledurilor pentru fiecare registru periferic. Astfel n
cele 4 porturi, care conin cte 8 pini, configurarea biilor poate fi efectuat diferit (Schema bloc
n fig. 3);
II. Delay reinerea n deplasare, care va conine 3 parametri de intrare 3 registri de uz general,
n care se vor seta niste valori (Schema bloc n fig. 4);
III. Shift_Lights aceast subrutin conine algoritmul deplasrii luminilor prin LED-uri, luminile se
vor deplasa spre stnga (Schema bloc fig. 5).

Subrutina - Secventa de instructiuni grupata intre o eticheta (label) si instructiune de returnare din subrutina
RET. Eticheta reprezinta o adresa in memoria de programe fiindui atribuit un nume de acces. In program va fi
reprezentata de un nume de eticheta urmata de (:)

In calitate de parametri al unei subrutine pot fi utilizati registrii de uz general. In asa mod pentru a transmite
date date de intrare in subrutina, inainte de a apela o subrutina este nevoie ca registrii utilizati ca parametri sa
fie initializati cu valorile de intrare dorite pentru acesti parametri. Iar dupa executia subrutinei se vor prelua
valorile din registrii rezervati parametrulilor de iesire.




Fig. 2 Fig. 3 Fig. 4


Fig. 5



3. Programul pentru Assembler:

.include "m16def.inc"; includem fisierul de
; definitie pentru
; controlerul ales
.cseg; indicam compilatorului ca deacum incolo
; va urma cod
.org 0; indicam adresa de inceput a codului
; care urmeaza
; Initializarea stivei
Init_Stiva: ; initializarea stivei
ldi R16, LOW(RAMEND); atrib. reg. o const.
out SPL, R16; transferul datelor
ldi R16, HIGH(RAMEND)
out SPH, R16


; Initializarea porturilor
Init_Ports:
push R16; inscrierea in stiva a reg.
push R17;
push R18
push R19
ldi R16, 0xCC; atribuirea valorii reg.
ldi R17, 0xDD
ldi R18, 0x77
ldi R19, 0x44
rcall Init_Lights ; chemarea subrutinei
pop R19 ; care va initializa
pop R18 ; porturile necesare
pop R17 ; cu ajutorul registrilor , fiecare reg.
pop R16 ; R16, R17, R18, R19 pot avea valori diferite

; MAIN_LOOP
Main_Loop:
push R16
push R17
push R18
ldi R16,0; atribuirea valorilor registrilor
ldi R17,0; care servesc ca parametri de
ldi R18,5; intrare pentru Delay
rcall Delay; chemarea subrutinei pentru delay
pop R18
pop R17
pop R16
push R16
rcall Shift_Lights; chemarea subrutinei
; pentru a deplasa luminile
pop R16
rjmp Main_Loop; salt la inceput

; Init_Lights
Init_Lights: ; initializarea porturilor
push R20
ldi R20, 0xFF
out DDRA, R20; setarea porturilor la iesire
out DDRB, R20;
out DDRC, R20;
out DDRD, R20;
out PORTA, R16; setarea portului cu valorile stabilite in
out PORTB, R17; Init_Ports
out PORTC, R18
out PORTD, R19
pop R20
ret ; iesirea din subrutina

; DELAY
Delay:
Loop: dec R16; decrem. valorii registrului
brne Loop; verificarea daca este egal cu zero si salt inapoi
; la decrementare daca rezultatul de true
dec R17 ; la fel decrementeaza valoarea lui R17
brne Loop; daca rezultatul true va face salt la Loop, astfel
dec R18 ; se va efectua din nou ciclul de decrementare
brne Loop ; a R16, si in rezultat vom avea o retinere destul
ret ; de mare,luind in consid.ca va avea loc si dec R18

; Shift_Lights
Shift_Lights:
Shift_PORTD:
in R16, PORTD ;se inscrie valorile portului in registru pentru
; a putea lucra mai departe cu registrul
lsl R16 ; shift logic la stinga, bitii << 1 , iar bitul 7 in bitul C
brcs Set_T_D ; daca bitul carry==1, adica a avut loc transportul T=1
clt ; daca carry==0, adica transportul nu a avut loc => bitul T==0
rjmp Continue_D ; salt la continuare
Set_T_D: ; setarea T==1, astfel vom folosi bitul T ca un buffer
Set ; si il vom atribui bitului 0 a PORTC
Continue_D: ; verificam bitul 7 din PORTA
sbic PORTA, 7 ; astfel daca bitul este "0"
; nu vom modifica nimic
sbr R16, 1 ; daca PORTA.7=1, el va veni in locul lui PORTC.0
; (PORTA.7==1)atunci R16.0==1
out PORTD, R16 ; daca PORTB.7==0
Shift_PORTC:
in R16, PORTC ; inscrierea valorilor din
; din PORTD in R16
lsl R16 ; shift logic la stinga
bld R16, 1 ; setam bitul PORTD.7 in PORTC.0
; care a fost salvat in T
brcs SET_T_C ; daca a avut loc transportul setam iarashi T="1"
; adica daca C==1
Clt ; T==0, daca C==0
rjmp Continue_C
Set_T_C:
Set ; setarea T==1
Continue_C:
out PORTC, R16
Shift_PORTB:
in R16, PORTB ; inscrierea valorilor din
; din PORTC in R16
lsl R16 ; shift logic la stinga
bld R16, 0 ; setam bitul PORTC.7 in PORTB.0
; care a fost salvat in T
brcs SET_T_B ; daca a avut loc transportul setam iarashi T="1"
clt ; T==0, adica C==0
rjmp Continue_B
Set_T_B:
Set ; setarea T==1
Continue_B:
out PORTB, R16
Shift_PORTA:
in R16, PORTA ; inscrierea valorilor din
; din PORTA in R16
lsl R16
bld R16, 0 ; setam bitul PORTA.7 in PORTA.0
; in bitul 0 din R16
out PORTA, R16
ret

Schema PROTEUS:




4. Informatie despre instruciunele folosite
1. PUSH aceast instruciune ncarc registrul Rd n STACK. SP (Stack Pointer) este decrementat dupa
efectuarea instruciunii.

2. POP aceast instruciune extrage registrul Rd din STACK. SP (Stack Pointer) este incrementat nainte
de efectuarea instruciunii POP.



3. RET ieirea din subrutin. Adresa de rentoarcere la executarea instruciunelor inainte de chemarea
subrutinei este ncrcat din Stack.

4. LSL transfer toi biii registrului de uz general Rd n partea stng. Bitul 0 este resetat 0. Bitul 7 este
incrcat n bitul Carry (C) din registrul de stare SREG.



5. IN ncarc datele din registrele periferice I/O n registrul de uz general Rd.

6. BLD copie valoarea bitului T din registrul de stare SREG n bitul indicat b din registrul de uz general
Rd .



7. CLT reseteaz bitul T din registrul de stare SREG

8. SET seteaz flagul T din registrul de stare SREG.

9. BRCS salt relativ condiionat. Testeaz bitul Carry (C) din registrul de stare SREG, i efectueaz salt
relativ la PC dac C este setat. Aceast instruciunea efectueaz salt relativ la PC n orice direcie (PC
63 destinaia + 64).

10. RCALL chemarea relativ a adresei n PC 2k+PC i PC+2k(words). Adresa de returnare (la
instruciunea dup efectuarea RCALL) este stocat n Stack.



Concluzie: n aceasta lucrare am folosit stiva, care este o memorie de tip LIFO, care am folosit-o pentru
memorarea temporar a datelor. Am utilizat subrutinelor, pe care le-am folosit pentru a optimiza programul.
Datorit subrutinelor programul complex a fost mprit n alte programe mai uoare. Am folosit subrutinele
cu parametri, pentru a putea transfera niste date pentru calcul.Am construit schema electrica in proteus.