programowanie_51.pdf

(113 KB) Pobierz
Programowanie mikrokontrolera 8051
Podane poniŇej informacje mogĢ pomc w nauce programowania mikrokontrolerw z
rodziny 8051. Opisane sĢ tu pewne specyficzne cechy tych procesorw a takŇe podane
przykþady rozwiĢzywania niektrych elementarnych zadaı programistycznych. Opis
uwzglħdnia tylko cechy podstawowe procesora, bez dodatkowych moŇliwoĻci oferowanych w
niektrych rozszerzeniach.
1. Specyfika rejestrw
Akumulator
Akumulator jest rejestrem roboczym, najbardziej uniwersalnym poniewaŇ moŇe byę
argumentem wielu rozkazw, w ktrych uŇycie innego rejestru nie jest moŇliwe. Nie
powinien byę on uŇywany do przechowywania danych w dþuŇszych sekwencjach programu,
gdyŇ prawdopodobnie bħdzie potrzebny do bieŇĢcych operacji w kolejnych rozkazach.
Mikrokontroler 8051, w przeciwieıstwie do wielu innych procesorw, nie posiada flagi
zera. W zwiĢzku z tym przy wykonywaniu rozkazw JZ i JNZ istotna jest zawsze bieŇĢca
wartoĻę akumulatora.
W rozkazach, w ktrych akumulator jest specjalnym argumentem zapisywany jest on jako
A. MoŇna teŇ traktowaę akumulator jako rejestr z obszaru SFR, i wwczas zapisywany jest on
jako ACC (asembler tþumaczy taki zapis na adres akumulatora). Na przykþad w poniŇszych
rozkazach informacja, Ňe jednym z argumentw jest akumulator zawarta jest juŇ w kodzie
rozkazu i nie jest moŇliwe uŇycie symbolu ACC:
CLR
A
; zerowanie akumulatora
MOVX A, @DPTR
; wpis zawartoĻci komrki pamiħci zewnħtrznej, adresowanej
przez DPTR, do akumulatora
ADD
A, @R0
; dodanie
do
akumulatora
zawartoĻci
komrki
pamiħci
wewnħtrznej adresowanej przez R0
W niektrych rozkazach uŇycie symbolu ACC jest konieczne. Chodzi o rozkazy, w
ktrych argumentem moŇe byę tylko adres komrki pamiħci wewnħtrznej, na przykþad:
PUSH ACC ; przesþanie akumulator na stos
DJNZ ACC, skok ; dekrementacja akumulatora i skok, jeĻli po dekrementacji
wartoĻę niezerowa
W pewnej grupie rozkazw argumentem moŇe byę zarwno A jak i ACC. NaleŇy
wwczas wybieraę wersjħ z uŇyciem symbolu A, poniewaŇ daje ona rozkaz o kodzie
krtszym o jeden bajt, na przykþad:
Prawidþowo
Nieoptymalne
INC
A
INC
ACC
; inkrementacja akumulatora
MOV
A, R7
MOV
ACC, R7
; wpis zawartoĻci rejestru R7 do
akumulatora
MoŇliwa jest nawet sytuacja, w ktrej argumentami jednego rozkazu sĢ symbole A oraz
ACC. Niekiedy moŇe to byę sensowne, jak w przykþadzie poniŇej (chociaŇ moŇna to zrobię w
prostszy sposb):
ADD
A, ACC
; dodanie akumulatora do akumulatora (pomnoŇenie przez 2 lepiej
wykonaę przez RL A)
894138492.004.png 894138492.005.png
 
A. Sterna
Programowanie mikrokontrolera 8051
2
XRL
A, ACC
; operacja Exclusive-OR akumulatora z nim samym (prostszy
wariant to CLR A)
Akumulator jest jednym z rejestrw z obszaru rejestrw specjalnych (SFR) ktre sĢ
adresowane bitowo. Przy operacjach bitowych bit akumulatora jest identyfikowany przez
uŇycie symbolu ACC, po kropce podawany jest numer bitu:
SETB
ACC.0
; ustawienie bitu 0 w akumulatorze
MOV
C, ACC.5
; przesþanie bitu 5 akumulatora do CY
Rejestr B
Rejestr B jest rejestrem pomocniczym, ktry ma specjalne zastosowanie w operacjach
mnoŇenia i dzielenia i nie moŇe byę w nich zastĢpiony innym rejestrem. W pozostaþych
przypadkach funkcjonuje na prawach komrki pamiħci i dlatego w wiħkszoĻci przypadkw
nie jest opþacalne uŇywanie go zamiast rejestrw R0 - R7. Rejestr B jest jednak adresowany
bitowo (nie jest to moŇliwe dla rejestrw R0 - R7) co ilustrujĢ poniŇsze przykþady:
SETB
B.3
; ustawienie bitu 3 w rejestrze B
MOV
B.5, C
; przesþanie CY do bitu 5 rejestru B
JB
B.0, skok
; skok jeĻli bit 0 rejestru B jest ustawiony
Rejestry R0 - R7
Rejestry R0 - R7 sĢ uniwersalnymi rejestrami umieszczonymi w poczĢtkowym obszarze
wewnħtrznej pamiħci RAM. PrzyporzĢdkowanie rejestrw do komrek pamiħci nie jest staþe
lecz zaleŇy od aktualnie wybranego banku pamiħci (bitami RS0, RS1 w rejestrze PSW).
PrzeþĢczanie bankw wykorzystuje siħ najczħĻciej w obsþudze przerwania.
Rejestry R0 i R1 sĢ wyrŇnione w ten sposb, Ňe tylko one mogĢ byę stosowane do
poĻredniego adresowania pamiħci wewnħtrznej.
2. Rozkazy arytmetyczne
Wykrywanie przepeþnienia
NaleŇy pamiħtaę, Ňe rozkazy inkrementacji i dekrementacji (INC, DEC) nie ustawiajĢ
Ňadnych flag, nawet jeĻli w wyniku operacji nastĢpi przejĻcie 0FFh ® 0 lub 0 ® 0FFh. Aby
wykryę takĢ zmianħ trzeba przeprowadzię dodatkowe sprawdzenie:
INC
R7
; inkrementacja R7
CJNE
R7, #0, dalej
...
; akcja wykonywana jeĻli nastĢpiþa zmiana 0FFh ® 0
dalej:
DEC
R7
; dekrementacja R7
CJNE
R7, #0FFH, dalej
...
; akcja wykonywana jeĻli nastĢpiþa zmiana 0 ® 0FFh
dalej:
JeĻli argumentem operacji jest komrka pamiħci, to sprawdzenie moŇe wyglĢdaę nastħpujĢco:
INC
direct
; inkrementacja komrki pamiħci
MOV
A, direct
; kopiujemy komrkħ pamiħci do A
JNZ
dalej
...
; akcja wykonywana jeĻli nastĢpiþa zmiana 0 ® 0FFh
894138492.006.png 894138492.001.png
 
A. Sterna
Programowanie mikrokontrolera 8051
3
dalej:
DEC
direct
; dekrementacja komrki pamiħci
MOV
A, direct
; kopiujemy komrkħ pamiħci do A
INC
A
; jeĻli nastĢpiþo przejĻcie 0 ® 0FFh, to po inkrementacji A = 0
JNZ
dalej
...
; akcja wykonywana jeĻli nastĢpiþa zmiana 0 ® 0FFh
dalej:
Ostatni przykþad z dekrementacjĢ moŇna rwnieŇ zrealizowaę nastħpujĢco:
DEC
direct
; dekrementacja komrki pamiħci
MOV
A, direct
; kopiujemy R0 do A
CJNE
A, #0FFH, dalej
...
; akcja wykonywana jeĻli nastĢpiþo przepeþnienie 0 ® 0FFh
dalej:
Dodawanie i odejmowanie
Rozkaz dodawania, ktrego pierwszym argumentem jest zawsze akumulator (w nim
pozostaje rwnieŇ wynik dodawania) jest dostħpny w dwch wariantach:
ADD - dodawanie bez przeniesienia
ADDC - dodawanie z przeniesieniem (flaga CY)
Przy dodawaniu wartoĻci jednobajtowych wykorzystywany jest rozkaz ADD:
ADD A, R7 ; A ¬ A + R7
Przy dodawaniu wartoĻci wielobajtowych, do operacji na najmþodszych bajtach naleŇy
uŇyę rozkazu ADD, przy kolejnych zaĻ rozkazu ADDC. PoniŇej pokazane jest to na
przykþadzie dodawania dwch wartoĻci 16 bitowych, podanych w parach rejestrw R4 | R5
oraz R6 | R7, wynik umieszczony bħdzie w parze rejestrw R6 | R7:
MOV
A, R5
; mþodszy bajt pierwszego skþadnika
ADD
A, R7
; sumowanie mþodszych bajtw
MOV
R7, A
; mþodszy bajt wyniku
MOV
A, R4
; starszy bajt pierwszego skþadnika
ADDC A, R6
; sumowanie starszych bajtw z uwzglħdnieniem przeniesienia
MOV
R6, A
; starszy bajt wyniku
Rozkaz odejmowania SUBB (odjemna zawsze w akumulatorze, tam rwnieŇ wynik) jest
wykonywany zawsze z poŇyczkĢ ktrej funkcjħ peþni flaga CY. Przy prostym odejmowaniu
wartoĻci jednobajtowych naleŇy pamiħtaę o wyzerowaniu CY;
CLR
C
; wyzerowanie poŇyczki
SUBB
A, R7
; A ¬ A - R7
MnoŇenie i dzielenie
Do mnoŇenia i dzielenia sþuŇĢ rozkazy MUL AB oraz DIV AB, majĢ one ustalone
argumenty, ktrymi sĢ zawsze akumulator i rejestr B:
MUL AB ; wynik mnoŇenia A * B jest wartoĻciĢ 16-bitowĢ B | A (mþodszy
bajt w A)
DIV AB ; wynik dzielenia A / B w A, reszta z dzielenia w B
WadĢ tych rozkazw jest stosunkowo dþugi czas wykonywania (4 cykle maszynowe).
Przy mnoŇeniu lub dzieleniu przez 2 moŇna wykorzystaę zamiast nich rozkazy przesuniħcia
(rotacji) akumulatora. Wykorzystywany jest przy tym fakt, Ňe mnoŇenie przez 2 odpowiada
przesuniħciu w lewo o jeden bit, zaĻ dzielenie przesuniħciu o jeden bit w prawo:
 
A. Sterna
Programowanie mikrokontrolera 8051
4
CLR
C
; wyzerowanie przeniesienia (bħdzie to najmþodszy bit wyniku)
RLC
A
; A ¬ A * 2, w CY 9 bit wyniku
CLR
C
; wyzerowanie przeniesienia (bħdzie to najstarszy bit wyniku)
RRC
A
; A ¬ A / 2, w CY reszta z dzielenia
JeĻli mamy pewnoĻę, Ňe wartoĻę w akumulatorze jest mniejsza niŇ 128 (a wiħc ACC.7
jest wyzerowany), to mnoŇenie przez 2 moŇna wykonaę stosujĢc tylko jeden rozkaz:
RL
A
; A ¬ A * 2 (ACC. 0 ¬ ACC.7)
3. Porwnywanie wartoĻci
Porwnanie z wykorzystaniem rozkazu CJNE
Lista rozkazw mikrokontrolera 8051 nie zawiera rozkazu porwnania, ktry ustawiaþby
tylko flagħ przeniesienia CY. Jest natomiast rozkaz CJNE (Compare and Jump if Not Equal)
w ktrym ustawiana jest flaga CY oraz wykonywany skok jeĻli porwnywane argumenty nie
sĢ rwne.
CJNE
arg_1, arg_2, skok
JeĻli arg_1 < arg_2 to CY = 1, skok wykonywany jest zawsze
JeĻli arg_1 >= arg_2 to CY = 0, skok wykonywany jest tylko jeĻli arg_1 > arg_2
Wykorzystanie rozkazu CJNE do sprawdzenia czy arg_1 < arg_2 polega na ustawieniu
adresu skoku na nastħpny rozkaz, tak wiħc niezaleŇnie od rezultatu porwnania skok jest
wykonywany zawsze w to samo miejsce. Caþy sens rozkazu CJNE sprowadza siħ wwczas do
ustawienia flagi CY.
Sprawdzenie, czy akumulator jest mniejszy od staþej:
CJNE
A, #data, skok
; jeĻli A < data to CY bħdzie ustawione
skok:
JC
mniejszy
...
; akcja wykonywana jeĻli A >= data
SJMP
dalej
mniejszy: ...
; akcja wykonywana jeĻli A < data
dalej:
JeĻli konieczne jest wykonanie akcji tylko w jednym przypadku, naleŇy odpowiednio
dobraę warunek skoku (JC lub JNC) tak, aby uzyskaę najprostszĢ strukturħ programu:
CJNE
A, #data, skok
; jeĻli A < data to CY bħdzie ustawione
skok:
JC
dalej
...
; akcja wykonywana jeĻli A >= data
dalej:
CJNE
A, #data, skok
; jeĻli A < data to CY bħdzie ustawione
skok:
JNC
dalej
...
; akcja wykonywana jeĻli A < data
dalej:
Stosunkowo rzadko wystħpuje sytuacja, w ktrej musimy wykonaę trzy rŇne akcje dla
trzech moŇliwych wynikw porwnania. Program wwczas wyglĢdaþby nastħpujĢco:
CJNE
A, #data, skok
; jeĻli A < data, CY bħdzie ustawione
...
; akcja wykonywana jeĻli A = data
SJMP
dalej
skok:
JC
mniejszy
...
; akcja wykonywana jeĻli A > data
894138492.002.png 894138492.003.png
 
A. Sterna
Programowanie mikrokontrolera 8051
5
SJMP
dalej
mniejszy: ...
; akcja wykonywana jeĻli A < data
dalej:
OczywiĻcie, jeĻli zaleŇy nam tylko na wyrŇnieniu przypadku rwnoĻci, to mamy
nastħpujĢce trzy przypadki:
1. OkreĻlona akcja ma byę wykonana tylko jeĻli argumenty sĢ rwne:
CJNE
A, #data, dalej
...
; akcja wykonywana jeĻli A = data
dalej:
2. OkreĻlona akcja ma byę wykonana tylko jeĻli argumenty sĢ rŇne:
CJNE
A, #data, rozne
SJMP
dalej
rozne:
...
; akcja wykonywana jeĻli A <> data
dalej:
3. JeĻli argumenty sĢ rwne, to wykonywana jest jedna akcja, w przeciwnym wypadku inna:
CJNE
A, #data, rozne
...
; akcja wykonywana jeĻli A = data
SJMP
dalej
rozne:
...
; akcja wykonywana jeĻli A <> data
dalej:
Oprcz pokazanej moŇliwoĻci porwnania akumulatora ze staþĢ, rozkaz CJNE umoŇliwia
jeszcze:
CJNE
A, direct, skok
; porwnanie akumulatora z komrkĢ pamiħci
CJNE
Rn, #data, skok
; porwnanie rejestru R0..R7 ze staþĢ
CJNE
@Ri, #data, skok ; porwnanie komrki pamiħci adresowanej przez R0 lub R1 ze
staþĢ
Porwnanie z wykorzystaniem odejmowania
Do porwnania wartoĻci moŇna zastosowaę rozkaz odejmowania, wykorzystujĢc fakt Ňe
operacja ta ustawia przeniesienie. Ilustruje to przykþad porwnania rejestru ze staþĢ:
CLR
C
; wyzerowanie poŇyczki
MOV
A, R7
; wpisanie wartoĻci porwnywanej do akumulatora
SUBB
A, #data
; jeĻli A < data to CY = 1, w przeciwnym wypadku CY = 0
JC
dalej
; skok jeĻli A < data (R7 < data)
...
; akcja wykonywana jeĻli R7 >= data
Podany powyŇej przykþad pozwala rozrŇnię dwa przypadki: R7 < data oraz R7 >= data.
JeĻli zachodzi potrzeba aby przypadek rwnoĻci byþ poþĢczony z relacjĢ mniejszoĻci
(rozrŇnienie przypadkw R7 <= data oraz R7 > data), to moŇna to zrobię na dwa pokazane
niŇej sposoby:
SETB
C
; ustawienie poŇyczki
MOV
A, R7
; wpisanie wartoĻci porwnywanej do akumulatora
SUBB
A, #data
; jeĻli A < data + 1 to CY = 1, w przeciwnym wypadku CY = 0
JC
dalej
; skok jeĻli A <= data (R7 < =data)
...
; akcja wykonywana jeĻli R7 > data
CLR
C
; wyzerowanie poŇyczki
MOV
A, #data
; wpisanie wartoĻci staþej do akumulatora
SUBB
A, R7
; jeĻli A < R7 to CY = 1, w przeciwnym wypadku CY = 0
JNC
dalej
; skok jeĻli A >= R7 (R7 < =data)
...
; akcja wykonywana jeĻli R7 > data
 
Zgłoś jeśli naruszono regulamin