Sunteți pe pagina 1din 15

Arhitectura Microprocesoarelor II Lucrarea de laborator nr.

4
1

Aplicaii ale microcontrolerului pe 8 bii PIC 16F84


1. Scopul lucrrii
Sunt prezentate o serie de programe scrise pentru microcontrolerul PIC 16F84. Folosirea
utilitarului MiSimDE permite simularea funcionrii unei platforme pentru dezvoltarea aplicaiilor
cu acest microcontroler.

2. Iniializarea programelor
Urmtorul program prezint modul n care se iniializeaz un program care conine tratarea
unei ntreruperi:

;**Definirea variabilelor pentru salvarea contextului in cazul deservirii unei
;ntreruperi
w_temp EQU 0x0C ;variabila in care se va stoca temporar W
status_temp EQU 0x0D ;variabila in care se va stoca temporar
STATUS

;**********************************************************************
ORG 0x000 ; adresa de salt in cazul unei
; operatii de resetare a procesorului
goto main ; salt la inceputul programului
; (sar peste vectorul de intreruperi)

ORG 0x004 ; locatia vectorului de intrerupere
movwf w_temp ; salvez continutul acumulatorului W
movf STATUS,0 ; transfer continutul lui STATUS in W
movwf status_temp ; salvez continutul lui STATUS

; Codul de deservire a intreruperii se plaseaza aici

movf status_temp,0 ; incarc vechiul continut al lui STATUS in W
movwf STATUS ; refac continutul lui STATUS
retfie ; ne introacem din rutina de deservire a
;intreruperii


;******************************PROGRAMUL PRINCIPAL***********************
main
; aici se va scrie programul aplicatiei

END ; directiva de sfarsit de program


Codul de deservire a ntreruperii se poate scrie explicit n locul indicat sau poate fi un salt la
o subrutin de deservire a ntreruperii. Vei avea grij ntotdeauna ca nainte de deservirea
ntreruperii s facei salvarea contextului de program, iar apoi s refacei acest context. Prin
contextul de program se nelege n general acumulatorul implicit (W) i registrul de stare
(STATUS). Utilizatorul poate ns salva i alte locaii de memorie dac acestea sunt folosite curent
att de programul principal ct i de rutina de deservire a ntreruperii. De observat c locaiile
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
2
folosite pentru stocarea lui W i a registrului STATUS (n cazul nostru 0Ch i 0Dh) nu ar trebui
folosite i n programul principal deoarece coninutul acestor locaii se va pierde la apariia unei
ntreruperi.


3. Exemple

Exemplul 1
S se programeze procesorul 16F84 astfel nct pe afiajul cu 7 segmente sa fie afiat cifra
FF atunci cnd o variabil din zona 0 de memorie (adresa 0Eh) este egal cu o alt variabil din zona
1 de memorie (adresa 8Fh).

;**Definirea de constante ce tin de arhitectura procesorului
STATUS EQU 0x03 ; registrul 03h din memoria de date
PORTB EQU 0x06 ; registrul 06h din memoria de date
TRISB EQU 0x86 ; registrul 86h din memoria de date

bank_select EQU 5 ; bitul de selectie al segmentului de memorie
; din registrul STATUS
zero_bit EQU 2 ; bitul de zero din registrul STATUS
w EQU 0
f EQU 1

;**Definirea variabilelor pentru salvarea contextului in cazul deservirii unei
intreruperi
w_temp EQU 0x0C ; variabia in care se va stoca temporar W
status_temp EQU 0x0D ; variabia in care se va stoca temporar
; registrul STATUS

;**Definirea variabilelor folosite de program
var_1 EQU 0x0E ; variabila din zona 0 de memorie
var_2 EQU 0x8F ; variabila din zona 1 de memorie

;**********************************************************************
ORG 0x0000 ; adresa de salt in cazul unei
; operatii de resetare a procesorului

goto main ; salt la inceputul programului (sar peste
;vectorul de intreruperi)
ORG 0x004 ; locatia vectorului de intrerupere
Movwf w_temp ; salvez continutul acumulatorului W
movf STATUS,w ; transfer continutul lui STATUS in W
movwf status_temp ; salvez continutul lui STATUS

; Codul de deservire a intreruperii se plaseaza aici

movf status_temp,w ; incarc vechiul continut al lui STATUS in W

movwf STATUS ; refac continutul lui STATUS
retfie ; ne intoarcem din rutina de deservire a
;intreruperii
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
3

;******************************PROGRAMUL PRINCIPAL******************
setup_port
bsf STATUS,bank_select ; pozitionarea in segmentul 1 de memorie
movlw 0 ; continutul registrului W devine 0
movwf TRISB ; se seteaza PORTB ca port de iesire
bcf STATUS,bank_select ; revenirea in segmentul 0 de memorie
movwf PORTB ; curatam PORTB (pe display avem 00)
return

write_to_port
movlw 0xFF
movwf PORTB
return

clear_port
movlw 0 ; continutul registrului W devine 0
movwf PORTB ; curatam PORTB (pe display avem 00)
return

clear_context
movlw 0 ;curatam registrul STATUS si W
movwf STATUS
return

main
call clear_context
call setup_port ; initializarea portului B (port de iesire)
bsf STATUS,bank_select ; pozitionarea in segmentul 1 de memorie
movf var_2,w ; stocam var_2 in W
bcf STATUS,bank_select ; pozitionarea in segmentul 0 de memorie
subwf var_1,w ; scadem var_1 din W (rezultatul ramane in W)
btfsc STATUS,zero_bit ; testam bitul de zero din registrul STATUS
call write_to_port ; daca (var_1==var_2)scriem FF la PORTB
btfss STATUS,zero_bit ; testam bitul de zero din registrul STATUS
call clear_port ; daca (var_1!=var_2)scriem 00 la PORTB

infinite_cycle
nop
goto infinite_cycle ; ne intoarcem pentru a asigura un
; ciclu infinit al procesorului

END ; directiva de sfarsit de program

n acest program se poate observa mecanismul unui test simplu: dac coninutul unui
registru este egal sau nu cu o anumit valoare. Etapele n acest caz sunt:
- se trece coninutul registrului n W
- cu o instruciune SUBLW se scade din W valoarea de test
- se testeaz apoi bitul Z (bitul 2) din registrul STATUS (cu instruciuni de tipul BTFSS
sau BTFSC)
ATENIE! ntre instruciunea SUBLW i BTFSS (sau BTFSC) nu trebuie s apar nici o
instruciune care s afecteze bitul Z din STATUS.
Dac valoarea cu care se compar un registru este chiar 0 ne putem baza pe faptul c
instruciunea MOVF afecteaz bitul de zero. Putem folosi deci o instruciune de tipul:
MOVF <registru>,1
dup care putem face testul bitului de zero din STATUS.
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
4
De asemenea se demonstreaz i modul apelrii unei subrutine: deoarece stiva hardware a
procesorului are doar 8 nivele nu se pot face mai mult de 8 apelri de tip CALL n CALL, depirea
acestei restricii nefiind semnalat n nici un fel.

Dup scrierea acesui program ntr-una din ferestrele de editare ale simulatorului se va
asambla i se va aciona butonul Run pentru pornirea procesului de simulare. Se va vizualiza
PlugIn-ul configurat mai sus. Se pote ncerca i o execuie pas cu pas pentru a urmri evoluia
registrelor implicate, prin inserarea unui punct de ntrerupere la nceputul programului principal.
Aceleai operaii pot fi executate i n cazul exemplelor urmtoare.


Exemplul 2
S se scrie un program care s adune dou variabile din segmentul 0 de memorie i s
afieze rezultatul pe display-ul cu 7 segmente. De asemenea s se semnaleze dac a aprut depire
prin aprinderea unui LED conectat la pinul 0 al portului A.

;**Definirea de constante ce tin de arhitectura procesorului
STATUS EQU 0x03 ; registrul 03h din memoria de date
PORTA EQU 0x05 ; registrul 05h din memoria de date
PORTB EQU 0x06 ; registrul 06h din memoria de date
TRISA EQU 0x85 ; registrul 85h din memoria de date
TRISB EQU 0x86 ; registrul 86h din memoria de date


bank_select EQU 5 ; bitul de selectie al segmentului de memorie
din STATUS
zero_bit EQU 2 ; bitul de zero din registrul STATUS
carry_bit EQU 0 ; bitul de carry din registrul STATUS
w EQU 0
f EQU 1

;**Definirea variabilelor pentru salvarea contextului in cazul deservirii unei
intreruperi
w_temp EQU 0x0C ; variabia in care se va stoca temporar W
status_temp EQU 0x0D ; variabia in care se va stoca temporar
; STATUS

;**Definirea variabilelor folosite de program
var_1 EQU 0x0E ; variabila 1 din zona 0 de memorie
var_2 EQU 0x0F ; variabila 2 din zona 0 de memorie

;**********************************************************************
ORG 0x000 ; adresa de salt in cazul unei
; operatii de resetare a procesorului
goto main ; salt la inceputul programului
; (sar peste vectorul de intreruperi)

ORG 0x004 ; locatia vectorului de intrerupere
movwf w_temp ; salvez continutul acumulatorului W
movf STATUS,w ; transfer continutul lui STATUS in W
movwf status_temp ; salvez continutul lui STATUS

; Codul de deservire a intreruperii se plaseaza aici

movf status_temp,w ; incarc vechiul continut al lui STATUS in W
movwf STATUS ; refac continutul lui STATUS
retfie ; ne introacem din rutina de deservire a
;intreruperii
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
5



;******************************PROGRAMUL PRINCIPAL************
setup_port
bsf STATUS,bank_select ; pozitionarea in segmentul 1 de memorie
movlw 0 ; continutul registrului W devine 0
movwf TRISB ; se seteaza PORTB ca port de iesire
movwf TRISA ; se seteaza PORTA ca port de iesire
bcf STATUS,bank_select ; revenirea in segmentul 0 de memorie
return

write_to_port
movwf PORTB ; scriu rezultatul adunarii la PORTB
return

clear_port
movlw 0 ; continutul registrului W devine 0
movwf PORTB ; curatam PORTB (pe display avem 00)
movwf PORTA ; curatam PORTA (led stins)
return

clear_context
movlw 0
movwf STATUS
return


lightup_led
movlw 0x01
movwf PORTA
return

main
call setup_port ; initializarea porturilor A si B (porturi de
;iesire)
call clear_port ; curatam porturile
call clear_context ; curatam contextul de program
movf var_1,w ; incarc var_1 in W
addwf var_2,w ; adun pe var_2 (rezultatul se stocheaza in
;W)
btfsc STATUS,carry_bit ; testez daca am depasire
call lightup_led ; daca da, aprind led-ul
btfss STATUS,carry_bit ; testez daca am depasire
call write_to_port ; daca nu, scriu rezultatul la PORTB

infinite_cycle
nop
goto infinite_cycle ; ne intoarcem pentru a asigura un
; ciclu infinit al procesorului

END ; directiva de sfarsit de program
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
6

Exemplul 3
S se scrie un program care s numere apariiile biilor de 1 din coninutul unui registru de
la adresa 0x11h. Rezultatul s se afieze pe display-ul cu 7 segmente.

;**Definirea de constante ce tin de arhitectura procesorului
STATUS EQU 0x03 ; registrul 03h din memoria de date
PORTB EQU 0x06 ; registrul 06h din memoria de date
TRISB EQU 0x86 ; registrul 86h din memoria de date

bank_select EQU 5 ; bitul de selectie al segmentului de memorie
; din registrul STATUS
zero_bit EQU 2 ; bitul de zero din registrul STATUS
carry_bit EQU 0 ; bitul de carry din registrul STATUS
w EQU 0
f EQU 1

;**Definirea variabilelor pentru salvarea contextului in cazul deservirii unei
;intreruperi
w_temp EQU 0x0C ; variabia in care se va stoca temporar W
status_temp EQU 0x0D ; variabia in care se va stoca temporar
STATUS

;**Definirea variabilelor folosite de program
contor EQU 0x0E ; variabila folosita pentru a realiza
ciclarea
numarator EQU 0x0F ; variabila care va numara bitii de 1
reg_lucru EQU 0x11 ; locatia de memorie vizata (registrul de
; lucru)

;**********************************************************************
ORG 0x000 ; adresa de salt in cazul une operatii de
resetare
; a procesorului
goto main ; salt la inceputul programului (sar peste
;vectorul
; de intreruperi)
ORG 0x004 ; locatia vectorului de intrerupere
movwf w_temp ; salvez continutul acumulatorului W
movf STATUS,w ; transfer continutul lui STATUS in W
movwf status_temp ; salvez continutul lui STATUS

; Codul de deservire a intreruperii se plaseaza aici

movf status_temp,w ; incarc vechiul continut al lui STATUS in W
movwf STATUS ; refac continutul lui STATUS
swapf w_temp,f
swapf w_temp,w ; refac continutul lui w
retfie ; ne introacem din rutina de deservire a
;intreruperii

;******************************PROGRAMUL PRINCIPAL******************
setup_port
bsf STATUS,bank_select ; pozitionarea in segmentul 1 de memorie
movlw 0 ; continutul registrului W devine 0
movwf TRISB ; se seteaza PORTB ca port de iesire
bcf STATUS,bank_select ; revenirea in segmentul 0 de memorie
return


Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
7
write_to_port
movf numarator,w ; incarc rezultatul numararii in W
movwf PORTB ; scriu pe W la PORTB
return

clear_port
movlw 0 ; continutul registrului W devine 0
movwf PORTB ; curatam PORTB (pe display avem 00)
return

clear_context
movlw 0 ;curatam registrul STATUS si W
movwf STATUS
return

main
call clear_context
call clear_port
call setup_port ; initializarea portului B (port de iesire)
movlw 0x08 ; Initializam contorul cu valoarea 8 (avem 8
biti de
movwf contor ; testat)
clrf numarator ; initializam cu 0 numaratorul
NEXT
rlf reg_lucru ; rotim stanga registrul vizat
btfsc STATUS,carry_bit ; testam bitul de CARRY (C) din STAUS
incf numarator ; daca este 1 incrementeaza continutul
numaratorului

decf contor ; decrementam contorul
btfss STATUS,zero_bit ; am facut 8 cicluri? Da => Z=1
goto NEXT ; nu, deci mai cicleaza o data...

call write_to_port ; scriu valoarea de la locatia "numarator"
; la PORTB
infinite_cycle
nop
goto infinite_cycle ; ne intoarcem pentru a asigura un
; ciclu infinit al procesorului

END ; directiva de sfarsit de program

Programul de mai sus se bazeaz tot pe faptul c instruciunile RRF i RLF realizeaz
operaia de rotaie prin intermediul bitului de CARRY din registrul STATUS. Se va realiza deci un
ciclu cu contor (se va cicla de 8 ori deoarece avem 8 bii de testat) n care se va testa de fiecare dat
bitul CARRY. Se poate folosi la fel de bine i instruciunea RRF n loc de RLF obinndu-se acelai
efect.

Exemplul 4
S se scrie un program care s numere apariiile valorii 0x11h din zona de registre generale
ale segmentului 0 de memorie ncepnd cu adresa 0x10h. Rezultatul s se afieze pe afiaj cu 7
segmente.

;**Definirea de constante ce tin de arhitectura procesorului
;**Vom avea adresare indirecta prin registru:
INDF EQU 0x00 ; registrul 00h din memoria de date
STATUS EQU 0x03 ; registrul 03h din memoria de date
FSR EQU 0x04 ; registrul 04h din memoria de date
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
8
PORTB EQU 0x06 ; registrul 06h din memoria de date
TRISB EQU 0x86 ; registrul 86h din memoria de date

bank_select EQU 5 ; bitul de selectie al segmentului de memorie
; din registrul STATUS
zero_bit EQU 2 ; bitul de zero din registrul STATUS
carry_bit EQU 0 ; bitul de carry din registrul STATUS
w EQU 0
f EQU 1

;**Definirea variabilelor pentru salvarea contextului in cazul deservirii unei
intreruperi
w_temp EQU 0x0C ; variabia in care se va stoca temporar W
status_temp EQU 0x0D ; variabia in care se va stoca temporar
STATUS

;**Definirea variabilelor folosite de program
contor EQU 0x0E ; variabila folosita pentru a realiza
;ciclarea
numarator EQU 0x0F ; variabila care va numara aparitiile valorii
; cautate
mem_base EQU 0x10 ; adresa primei locatii de memorie din
; segmentul 0 de memorie
mem_size EQU 0x40 ; numarul de registri de uz general din
; segmentul 0 de memorie (adica 68)
search_val EQU 0x11 ; valoarea dupa care se face cautarea

;**********************************************************************
ORG 0x000 ; adresa de salt in cazul unei operatii de
resetare
; a procesorului
Goto main ; salt la inceputul programului (sar peste
vectorul
; de intreruperi)
ORG 0x004 ; locatia vectorului de intrerupere
movwf w_temp ; salvez continutul acumulatorului W
movf STATUS,w ; transfer continutul lui STATUS in W
movwf status_temp ; salvez continutul lui STATUS

; Codul de deservire a intreruperii se plaseaza aici

movf status_temp,w ; incarc vechiul continut al lui STATUS in W
movwf STATUS ; refac continutul lui STATUS
swapf w_temp,f
swapf w_temp,w ; refac continutul lui w
retfie ; ne introacem din rutina de deservire a
;intreruperii


;************************PROGRAMUL PRINCIPAL***********************
setup_port
bsf STATUS,bank_select ; pozitionarea in segmentul 1 de memorie
movlw 0 ; continutul registrului W devine 0
movwf TRISB ; se seteaza PORTB ca port de iesire
bcf STATUS,bank_select ; revenirea in segmentul 0 de memorie
return

write_to_port
movf numarator,0 ; incarc rezultatul numararii in W
movwf PORTB ; scriu pe W la PORTB
return
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
9

clear_port
movlw 0 ; continutul registrului W devine 0
movwf PORTB ; curatam PORTB (pe display avem 00)
return

clear_context
movlw 0 ;curatam registrul STATUS si W
movwf STATUS
return

main
call clear_context
call clear_port
call setup_port ; initializarea portului B (port de iesire)
movlw mem_size ; initializam contorul cu valoarea mem_size
movwf contor
clrf numarator ; initializam cu 0 numaratorul
movlw mem_base ; initializam registrul FSR cu valoarea
mem_base
movwf FSR
NEXT
movlw search_val ; scad valoarea cautata din valoarea stocata
la
subwf INDF,0 ; locatia curenta de memorie (rezultatul se
stocheaza in W)
btfsc STATUS,zero_bit ; testam bitul de zero din registrul STATUS
incf numarator ; daca este 1 incrementeaza continutul
;numaratorului
incf FSR ; inaintez cu o pozitie in segmentul 0 de
;memorie

decf contor ; decrementam contorul
btfss STATUS,zero_bit ; am ajuns la sfarsitul segmentului?
goto NEXT ; nu, deci mai cicleaza o data...

call write_to_port

infinite_cycle
nop
goto infinite_cycle ; ne intoarcem pentru a asigura un ciclu
;infinit al procesorului

END ; directiva de sfarsit de program

Acest program are rolul de a ilustra mecanismul adresrii indirecte pentru PIC16F84. n
esen se dorete extragerea informaiei de la o locaie de memorie a crei adres este stocat ntr-o
alt locaie de memorie. Etapele de baz sunt urmtoarele:
se scrie adresa locaiei vizate n registrul FSR;
n registrul INDF se va afla coninutul locaiei vizate.








Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
10
Exemplul 5
S se scrie un program n care s se completeze cu AAh toate registrele de uz general din
segmentul 0 de memorie, apoi s le tearg (sa le completeze cu 0). Dac tergerea a fost efectuat
se vor aprinde led-urile 0,1,2,3 (corespunztoare pinilor RB<0>...RB<3>).



LIST P=16F84, R=DEC

; definirea RAM-ului
STATUS EQU 3 ; registrul 03h din memoria de date
FSR EQU 4 ; registrul 04h din memoria de date
INDF EQU 0x00 ; adresare indirecta
RA EQU 5 ; se definesc variabilele pentru porturi
RB EQU 6
TRISA EQU 0x85 ; registrul 5 din segmentul 2 de memorie
TRISB EQU 0x86 ; registrul 6 din segmentul 2 de memorie
RP0 EQU 5 ; bitul 5 din registrul STATUS

ORG 0x000 ; se va defini RAM-ul incepand cu adresa 0h
BSF STATUS,RP0
MOVLW 0X00
MOVWF TRISB ; portul B configurat ca port de iesire
BCF STATUS, RP0 ; se reseteaza bitul 5 din registrul STATUS
pentru
; scrierea in segmentul 0 de memorie
MOVLW 0x00 ; coninutul registrului W este incarcat cu
0x00
MOVWF RB ; se asigur ca ledurile sunt stinse
MOVLW 0x0C ; coninutul registrului W este incarcat cu
0x0C
; (adres de la care ncep registrele
generale)
MOVWF FSR ; registrul FSR ia valoarea 0x0c
; se ncepe adugarea de valori n registrele
;generale
ADAUGAREG
MOVLW 0xAA
MOVWF INDF ; registrul INDF ia valoare 0xAA
INCF FSR ; se va incrementa registrul FSR pna va
parcurge
; toata zona de memorie
; cu registre generale (de la 0x0C la 0x2F)
MOVLW 0x2F ; coninutul registrului W este 0x2F
SUBWF FSR,0 ; se scade din registrul FSR valoarea 0x2F
BTFSS STATUS,2 ; se testeaz daca bitul 2 din registrul
STATUS este 0,
; daca este 1 se sare peste instruciunea
urmtoare
GOTO ADAUGAREG

MOVLW 0x0C
MOVWF FSR ; se va ncarca FSR cu nceputul zonei de
memorie
; a registrelor generale (FSR la inceputul
GPR)

STERGEREG ; se ncepe stergerea de valori n registrele
;generale
CLRF INDF
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
11
INCF FSR
MOVLW 0x2F
SUBWF FSR,0
BTFSS STATUS,2
GOTO STERGEREG

MOVLW 0x0F
MOVWF RB ; se vor aprinde cele 4 led-uri
END ; sfrit de program


Exemplul 6
S se simuleze un semafor:
- led-ul rou se va aprinde pentru 15 secunde
- led-ul galben se va aprinde pentru 2 secunde
- led-ul verde se va aprinde pentru 15 secunde

LIST P=16F84,R=DEC
; ROSU RB:<0>, GALBEN RB:<2>, VERDE RB:<1>
; TRAFFIC LIGHT

STATUS EQU 3
RA EQU 5
RB EQU 6
R0 EQU 0X0C
R1 EQU 0X0D
R2 EQU 0X0E
TRISA EQU 0X85
TRISB EQU 0X86
RP0 EQU 5 ; bitul 5 din registru STATUS

; Definirea variabilelor
DATR1 EQU 133
DATR2 EQU 250

ORG 0
BSF STATUS,RP0
MOVLW 0
MOVWF TRISB ; PORTB ca port de ieire
BCF STATUS,RP0

BEGIN
MOVLW 00000001
MOVWF RB ; se aprinde led-ul rosu
MOVLW 150 ; pentru 15 secunde
CALL DELAY

MOVLW 000000010
MOVWF RB ; se aprinde led-ul galben
MOVLW 20 ; pentru 2 secunde
CALL DELAY

MOVLW 00000100
MOVWF RB ; se aprinde led-ul verde
MOVLW 150 ; pentru 15 secunde
CALL DELAY

GOTO BEGIN
DELAY ; DELAY 0.1 Sec
MOVWF R0
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
12
DELAY3
MOVLW DATR1
MOVWF R1
DELAY2
MOVLW DATR2
MOVWF R2
DELAY1
DECFSZ R2 ; (R2)(R2)-1 ; Z=1 nu executa; Z=0
;executa
GOTO DELAY1
DECFSZ R1
GOTO DELAY2
DECFSZ R0
GOTO DELAY3
RETLW 0 ; (PC)TOS; (W)0
END


Exemplul 7
S se scrie un program care s copieze coninutul primilor 10 registre de uz general din
segmentul 0 de memorie n segmentul 1 de memorie ncepnd cu adresa 0x90h.

;**Definirea de constante ce tin de arhitectura procesorului
INDF EQU 0x00 ; registrul 00h din memoria de date
STATUS EQU 0x03 ; registrul 03h din memoria de date
FSR EQU 0x04 ; registrul 04h din memoria de date
PORTB EQU 0x06 ; registrul 06h din memoria de date
TRISB EQU 0x86 ; registrul 86h din memoria de date

bank_select EQU 5 ; bitul de selectie al segmentului de memorie
; din registrul STATUS
zero_bit EQU 2 ; bitul de zero din registrul STATUS
carry_bit EQU 0 ; bitul de carry din registrul STATUS
w EQU 0
f EQU 1

;**Definirea variabilelor pentru salvarea contextului in cazul deservirii unei
intreruperi
w_temp EQU 0x0C ; variabia in care se va stoca temporar W
status_temp EQU 0x0D ; variabia in care se va stoca temporar
;STATUS

;**Definirea de variabile utile programului
contor EQU 0x20 ; locatie folosita pentru stocarea contorului
buffer1 EQU 0x21 ; locatie pentru stocarea diferitelor
variabile
; (pt. seg. 0)
buffer2 EQU 0x8C ; locatie pentru stocarea diferitelor
variabile
; (pt. seg. 1)
mem_size EQU 0x0A ; numarul de regisre de uz general care
trebuie
; copiati (adica 10)
mem_base_0 EQU 0x0C ; adresa primului registru de uz general
; din segmentul 0 de memorie
mem_base_1 EQU 0x90 ; adresa primului registru de uz general
; din segmentul 1 de memorie

Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
13
;**********************************************************************
ORG 0x000 ; adresa de salt in cazul unei operatii de
;resetare
; a procesorului
goto main ; salt la inceputul programului (sar peste
;vectorul de intreruperi)
ORG 0x004 ; locatia vectorului de intrerupere
movwf w_temp ; salvez continutul acumulatorului W
movf STATUS,w ; transfer continutul lui STATUS in W
movwf status_temp ; salvez continutul lui STATUS

; Codul de deservire a intreruperii se plaseaza aici

movf status_temp,w ; incarc vechiul continut al lui STATUS
;in W
movwf STATUS ; refac continutul lui STATUS
retfie ; ne intoarcem din rutina de deservire a
;intreruperii

;************************PROGRAMUL PRINCIPAL***********************
ADDR_SEG_0 ; se calculeaza adresa sursei
movlw mem_size ; scriem in W valoarea 10
movwf buffer1 ; scriem pe "10" intr-o locatie temporara din
segmentul 0

movlw contor ; preluam valoarea curenta a "contorului" in
;W
movwf FSR
movf INDF,0

subwf buffer1,0 ; scadem valoarea curenta a "contorului" din
; 10
addlw mem_base_0 ; si adunam la "mem_base_0"
return ; ne intoarcem din rutina

ADDR_SEG_1 ; se calculeaza adresa destinatiei
movlw mem_size ; scriem in W valoarea 10
movwf buffer1 ; scriem pe "10" intr-o locatie temporara din
segmentul 0

movlw contor ; preluam valoarea curenta a "contorului" in
; W
movwf FSR
movf INDF,0

subwf buffer1,0 ; scadem valoarea curenta a "contorului" din
;10
addlw mem_base_1 ; si adunam la "mem_base_1"
return ; ne intoarcem din rutina

COPY ; aici se face copierea
bcf STATUS, bank_select ; ne pozitionam pe segmentul 0 de memorie
call ADDR_SEG_0 ; calculam adresa locatiei DE UNDE se copiaza
; (la iesirea din rutina aceasta se afla in
;W)
movwf FSR ; scriem adresa calculata mai sus in FSR
movf INDF,0 ; preluam continutul adresei calculate in W

bsf STATUS,bank_select ; ne pozitionam pe segmentul 1 de memorie
movwf buffer2 ; salvam informatia de mai sus intr-o locatie
; temporara din SEGMENTUL 1
Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
14
; (avem nevoie sa fie in segmentul 1)
bcf STATUS, bank_select ; ne pozitionam pe segmentul 0 de memorie

call ADDR_SEG_1 ; calculam adresa locatiei UNDE se copiaza
; (la iesirea din rutina aceasta se afla in
W)
bsf STATUS, bank_select ; ne pozitionam pe segmentul 1 de memorie
movwf FSR ; scriem adresa calculata mai sus in FSR
movf buffer2,0 ; preluam continutul locatiei temporare in W
; (care reprezinta informatia de copiat)
movwf INDF ; scriem informatia de mai sus la locatia
;calculata
return ; ne intoarcem din rutina


main
movlw mem_size ; Initializarea contorului
movwf contor

NEXT
call COPY ; apelam rutina de copiere
decf contor ; decrementam contorul
btfss STATUS,zero_bit ; testam contorul daca a ajuns la 0
goto NEXT ; daca nu mai ciclam o data

INFINITE_LOOP
nop
goto INFINITE_LOOP ; asiguram un ciclu infinit al procesorului

END ; directiva de sfarsit de program

Programul prezint o complexitate ceva mai mare deoarece se folosesc adresri indirecte,
teste, un ciclu cu contor ct i apeluri de subrutin. Copierea unui bloc de date dintr-un segment de
memorie n altul implic translatri repetate dintr-un segment n altul. Algoritmul programului
principal e foarte simplu: se apeleaz procedura COPY de un numr de ori egal cu contorul.
Algoritmul de copiere al unei locaii de memorie dintr-un un segment n altul presupune:
identificarea locaiei de memorie de unde se face copierea (adic aflarea adresei acesteia).
Formula pentru determinarea acestei adrese este:
mem_base_0+(mem_size-[contor])
unde prin [contor] nelegem coninutul locaiei de memorie cu adresa contor. Acest lucru
este realizat de rutina ADDR_SEG_0;
cu adresa calculat mai sus i folosind adresarea indirect se salveaz coninutul locaiei
respective ntr-o adres buffer din segmentul 1 de memorie. Am nevoie de acest lucru
pentru c n mecanismul adresrii indirecte n interiorul segmentului 1 sunt nevoit s folosesc
W (W fiind ocupat, aducerea direct a informaiei vizate direct din segmentul 0 la locaia
dorit din segmentul 1 este practic imposibil);
se calculeaz dup o formul identic cu cea de mai sus adresa locaiei destinaie:
mem_base_1+(mem_size-[contor])
Calculul acestei adrese este fcut de procedura ADDR_SEG_1;
se transfer coninutul locaiei buffer la locaia cu adresa calculat cu formula de mai sus.

Arhitectura Microprocesoarelor II Lucrarea de laborator nr. 4
15


TEME:
1. S se programeze procesorul 16F84 astfel nct pe afiajul cu 7 segmente s fie afiat cifra
FF atunci cnd o variabil din zona 0 de memorie este egal cu o alt variabil din zona 1 de
memorie (model de rezolvare: exemplul 1).
2. S se scrie un program care s adune dou variabile din segmentul 0 de memorie i sa afieze
rezultatul pe afiajul cu 7 segmente. De asemenea, s se semnaleze dac a aprut depire
prin scrierea n memorie a valorii FFH n locaia 15H (model de rezolvare: exemplul 2).
3. S se scrie un program care s numere apariiile biilor de 1 din coninutul unui registru de la
adresa 0x11. Rezultatul s se afieze pe afiajul cu 7 segmente (model de rezolvare:
exemplul 3).
4. S se scrie un program care s numere apariiile valorii 0x11 din zona de registre generale ale
segmentului 0 de memorie. Rezultatul s se afieze pe afiajul cu 7 segmente (model de
rezolvare: exemplul 4).
5. S se scrie un program n care sa se completeze cu AAh toate registrele de uz general din
segmentul 0 de memorie, apoi sa-i copieze n segmentul 2 de memorie. Dac copierea a fost
efectuat se vor aprinde led-ul 0 pentru 10 secunde i apoi led-ul 1 pentru 20 secunde led-
urile corespunztoare pinilor RB:<0> si RB:<1> (model de rezolvare: exemplul 5).
6. S se simuleze un numrtor zecimal de la 00-60 (va numra 1 minut). Se va folosi o rutin
de conversie hexazecimal-decimal. S se afieze acest lucru pe afiajul cu 7 segmente.

S-ar putea să vă placă și