04_Avrasm - hex2dec.pdf

(73 KB) Pobierz
305452952 UNPDF
http://www.easy-soft.tsnet.pl/
AVR Asembler:
Konwersja liczba HEX na DEC.
Najprostszą metodą konwersji liczb szesnastkowych na dziesiętne jest liczenie ile razy dana waga dziesiętna
„zmieści się” w liczbie szesnastkowej. W języku asembler operację tę przeprowadza się najczęściej przez
odejmowanie wagi dziesiętnej i liczenie ilości operacji odejmowania do momentu ustawienia flagi przeniesienia
C.
Przykład programowania:
konwersja liczb szesnastkowych na dziesiętne.
Na listingu 1 przedstawiono przykład realizacji funkcji konwersji liczb szesnastkowych o długości 16 bitów (a
więc z zakresu od 0 do 65535) na dziesiętne. W celu lepszego zrozumienia zasady działania, procedura
napisana jest mało oszczędnie. Oczywiście może być wykorzystana w takiej postaci jak prezentowana na
listingu 1, może być również zmodyfikowana tak, aby używała mniej zasobów mikrokontrolera.
Początek przykładowego programu wykorzystującego konwersję, zawiera definicję typu użytego
mikrokontrolera oraz tablicy wektorów przerwań. Następnie zadeklarowane są zmienne, które będą
przechowywać poszczególne mnożniki poszczególnych wag dziesiętnych cyfry po konwersji. Noszą one nazwy
bcd_1, bcd_10, bcd_100, bcd_1tys i bcd_10tys w zależności od potęgi mnożnika przechowywanej wagi
dziesiętnej (tzn. bcd_1 to 10 0 , bcd_10 to 10 1 itd.). Zmienne var1msb, var1lsb, var2msb i var2lsb
wykorzystywane są przez funkcje arytmetyczne (dodawanie i odejmowanie 16-bitowe). Zmienne z „2”
wewnątrz nazwy zadeklarowane są w obszarze rejestrów umożliwiających realizację rozkazów zawierających
stałe jako argumenty wywołania. Zmienna temp to tradycyjnie już zmienna ogólnego przeznaczenia, na
wszelkie tymczasowo przeprowadzane obliczenia. Nie przechowuje ona żadnych istotnych dla pracy aplikacji
informacji. Do zmiennych A1 i A2 należy przed wywołaniem funkcji hex2dec wpisać liczbę do konwersji.
Przykład wywołania umieszczony jest w pętli głównej programu.
Konwersja rozpoczyna się od etykiety hex2dec. Jak wspomniano wyżej, przed jej wywołaniem, należy do
zmiennych A2 i A1 wpisać odpowiednio starszy i młodszy bajt liczby do konwersji. Zmienne te nie są
modyfikowane w czasie pracy funkcji.
Funkcja dodawania i funkcja odejmowania oczekują argumentów w zmiennych var1msb:var1lsb oraz
var2msb:var2lsb . Pierwsza para zmiennych oprócz tego, że zawiera składnik sumy lub odjemną różnicy, to
również przechowywać będzie wynik operacji dodawania czy odejmowania. Istotną cechą funkcji
arytmetycznych jest również ta, że nie modyfikują one wartości drugiej pary rejestrów. W związku z tym, na
przykład odjemna może być raz załadowana i rozkaz ten nie musi być powtarzany. Rozkazy
ldi var2lsb,low(c10tys)
ldi var2msb,high(c10tys)
ładują dzielnik dla wagi dziesiątek tysięcy tu równoważny z odjemnikiem dla operacji odejmowania. Następnie
sprawdzane jest, ile razy można odjąć wartość c10tys od liczby do konwersji aby bit przeniesienia (oznaczający,
że odjemna jest mniejsza od odjemnika) nie został ustawiony. Przy każdej operacji odejmowania zwiększany
jest stan licznika zawierającego mnożnika wagi dziesiętnej – w tym przypadku – dziesiątek tysięcy.
loop1_10tys:
inc bcd_10tys
rcall sub_16_16
brcc loop_10tys
Jeśli flaga przeniesienia zostanie ustawiona, oznacza to, że odjemna jest mniejsza od odjemnika. W takim
przypadku ostatnio wykonana operacja odejmowania musi być cofnięta przez operację odwrotną, tj. dodanie
odjemnika oraz zmniejszenie licznika wykonanych operacji. Funkcja realizująca odejmowanie nie modyfikuje
wartości odjemnika. W związku z tym, że umieszczony jest on w parze zmiennych wspólnych dla
zaimplementowanych funkcji dodawania i odejmowania oraz wykorzystywanych jako drugi argument funkcji
dodawania, prosta realizacja dwóch rozkazów asemblera rozwiązuje problem uzupełnienia wartości.
rcall add_16_16
dec bcd_10tys
Taki sam tok postępowania obowiązuje w celu policzenia mnożnika dla tysięcy, setek i dziesiątek. Tylko w
przypadku jednostek wystarczy proste przepisanie wartości młodszego bajtu do licznika jednostek po wykonaniu
całości procedury konwersji od dziesiątek tysięcy do 10.
J.Bogusz „AVR Asembler: Konwersja liczb HEX na DEC”
STRONA 1/3
305452952.001.png
http://www.easy-soft.tsnet.pl/
;przykład realizacji funkcji konwersji liczby 16 bitowej
;liczby szesnastkowej na BCD
.include "8515def.inc"
;zmienne przechowujące po konwersji:
.def bcd_1
= R0
;-jednostki
.def bcd_10
= R1
;-dziesiątki
.def bcd_100
= R2
;-setki
.def bcd_1tys = R3
;-tysiące
.def bcd_10tys = R4
;-dziesiątki tysięcy
.def var1lsb
= R5
;zmienne dla operacji arytmetycznych
.def var1msb
= R6
.def var2lsb
= R19
.def var2msb
= R20
.def temp
= R16
;zmienna ogólnego przeznaczenia
.def A1
= R17
;tu liczba do konwersji (młodszy bajt)
.def A2
= R18
;- / / - (starszy bajt)
.org 0
;---------------------------------------------
;wektory obsługi przerwań
;---------------------------------------------
rjmp RESET
;po Reset
reti
;External Interrupt 0
reti
;External Interrupt 1
reti
;T/C1 Compare Match A
reti
;T/C1 Compare Match B
reti
;T/C1 Overflow
reti
;T/C0 Overflow
reti
;SPI Transfer Complete
reti
;UART Rx Complete
reti
;UART Data Register Empty
reti
;UART Tx Complete
reti
;Analog Comparator
;---------------------------------------------
;program główny
;---------------------------------------------
RESET:
out SPL,temp
ldi temp,high(RAMEND)
out SPH,temp
;ustawienie wskaźnika stosu
ldi A1,$A0
;liczba EAA0 (60064 dzies.) jako parametr
rcall hex2dec
;wywołania funkcji konwersji
loop: rjmp loop
;---------------------------------------------
;konwersja HEX na BCD
;wejście: liczba do konwersji w A2:A1
;zakończenie: wynik konwersji w bcd_1... bcd_10000
;---------------------------------------------
;wykonywana dla liczby 16-bitowej, to jest z zakresu
;od 0 do 65535
.equ c10tys = 10000
;stałe (odjemniki)
.equ c1tys = 1000
.equ c100 = 100
.equ c10 = 10
hex2dec:
clr bcd_1
;zerowanie zmiennych - liczników
clr bcd_10
clr bcd_100
clr bcd_1tys
clr bcd_10tys
mov var1lsb,A1
;załadowanie liczby do konwersji do rejestrów roboczych
mov var1msb,A2
;KONWERSJA „10 TYS.”
ldi var2lsb,low(c10tys) ;załadowanie odjemnika 10 tys.
ldi var2msb,high(c10tys)
J.Bogusz „AVR Asembler: Konwersja liczb HEX na DEC”
STRONA 2/3
reti
;T/C1 Capture Event
ldi temp,low(RAMEND)
ldi A2,$EA
;uruchomienie konwersji
305452952.002.png
http://www.easy-soft.tsnet.pl/
loop_10tys:
;liczenie ile razy 10 tys.zmieści się w liczbie do konw.
inc bcd_10tys
;zwiększenie licznika 10-tysięcy o 1
brcc loop_10tys
;powtórka, jeśli nie było przeniesienia
rcall add_16_16
;dodanie odjemnika aby wrócić do wartości
;sprzed działania
dec bcd_10tys
;zmniejszenie liczby 10-tysięcy
;KONWERSJA „1 TYS.”
ldi var2lsb,low(c1tys) ;załadowanie odjemnika 1 tys.
ldi var2msb,high(c1tys)
loop_1tys:
;liczenie ile razy 1 tys. zmieści się w liczbie do
konwersji
inc bcd_1tys
;zwiększenie licznika tysięcy o 1
rcall sub_16_16
;powtórka, jeśli nie było przeniesienia
rcall add_16_16
;dodanie odjemnika aby wrócić do wartości
;sprzed działania
dec bcd_1tys
;zmniejszenie liczby tysięcy
;KONWERSJA „100”
ldi var2lsb,c100
;załadowanie odjemnika 100
clr var2msb
loop_100:
;liczenie ile razy 100 zmieści się w liczbie do konwersji
inc bcd_100
rcall sub_16_16
brcc loop_100
rcall add_16_16
dec bcd_100
;KONWERSJA „10”
ldi var2lsb,c10
;załadowanie odjemnika 10
clr var2msb
loop_10:
inc bcd_10
rcall sub_16_16
brcc loop_10
rcall add_16_16
dec bcd_10
;KONWERSJA „1”
;pozostała reszta z operacji odejmowania to jednostki
mov bcd_1,var1lsb
ret
;liczenie ile razy 100 zmieści się w liczbie do konwersji
;---------------------------------------------
;dodawanie dwóch liczb 16-bitowych
;pierwsza liczba w var1msb:var1lsb, druga w var2msb:var2lsb
;wynik przechowywany w var1msb:var1lsb + flaga C
;---------------------------------------------
add_16_16:
add var1lsb,var2lsb
;dodanie młodszych bajtów bez uwzględnienia flagi C
adc var1msb,var2msb
;dodanie starszych bajtów z uwzględnieniem flagi C
ret
;powrót do wywołania z ustawioną lub nie flagą C
;---------------------------------------------
;odejmowanie dwóch liczb 16-bitowych
;pierwsza liczba w var1msb:var1lsb, druga w var2msb:var2lsb
;wynik przechowywany w var1msb:var1lsb + flaga C
;---------------------------------------------
sub_16_16:
sub var1lsb,var2lsb ;odejmowanie młodszych bajtów
sbc var1msb,var2msb ;odejmowanie starszych bajtów z uwzględnieniem flagi C
ret ;powrót do wywołania z ustawioną lub nie flagą C
Listing 1. Program konwersji 2-bajtowych liczb szesnastkowych na dziesiętne.
Jacek Bogusz
jacek.bogusz@ep.com.pl
J.Bogusz „AVR Asembler: Konwersja liczb HEX na DEC”
STRONA 3/3
rcall sub_16_16
;wywołanie funkcji odejmowania
brcc loop_1tys
;wywołanie funkcji odejmowania
305452952.003.png
Zgłoś jeśli naruszono regulamin