05_Avrasm - licznik.pdf

(155 KB) Pobierz
305452984 UNPDF
http://www.easy-soft.tsnet.pl/
AVR Asembler:
Licznik.
Podczas lektury poprzedniego odcinka kursu poznaliśmy podstawy organizacji pamięci oraz wykorzystania
zasobów mikrokontrolera AT90S8515. Nauczyliśmy się w jaki sposób skonfigurować linie portów
mikrokontrolera, jak odczytać stan portu wejściowego i jak zaświecić diodę LED dołączoną do wyprowadzenia
mikrokontrolera. Poznaliśmy też sposób użycia przerwania zewnętrznego do realizacji licznika. Dziś posuniemy
się o krok dalej. Do mikrokontrolera dołączymy cyfrę LED i nauczymy się nią sterować. Wszystko na przykładzie
prostej aplikacji licznika.
Przykład programowania:
Wyświetlanie stanu licznika.
Zbudowany poprzednio licznik wyświetlał wartość zliczonej liczby impulsów w postaci zmieniającego się stanu
diod LED dołączonych do portu A. Informację w takiej postaci jest mało czytelna dla przeciętnego obserwatora.
Zastąpmy diody LED wyświetlaczem 7-segmentowym dołączonym do portu A. Niech na początek będzie to
pojedyncza cyfra o wspólnej anodzie. Nie może to być zbyt duży wyświetlacz, ponieważ nie będą używane
żadne układy buforów a prąd segmentów może uszkodzić porty wyjściowe mikrokontrolera. Taki o wysokości
około 8..10 mm będzie najbardziej odpowiedni. Model zbudowałem z użyciem TDSY-3150 firmy Vishay. Anodę
dołączyłem bezpośrednio do +5V, natomiast katody do wyprowadzeń portu A mikrokontrolera, ale z użyciem
rezystorów szeregowych o wartości 470Ω. Sposób w jaki podłączyłem swój wyświetlacz przedstawiono na
rysunku 1.
Rysunek 1. Sposób dołączenia wyświetlacza LED do mikrokontrolera dla programu z artykułu.
Na listingu 1 przedstawiono przykład realizacji zmodyfikowanego programu licznika z odcinka 1-go kursu. W
przykładzie tym mikrokontroler zlicza impulsy od 0 do 9 i wyświetla stan licznika na dołączonej pojedynczej
cyfrze wyświetlacza LED.
W programie (identycznie jak w poprzednim odcinku) ustawiany jest adres stosu mikrokontrolera oraz sposób
reakcji na zewnętrzne przerwanie INT0. Port D ustawiany jest jako wejściowy, port A w całości jako wyjściowy.
Interesująca nas w tym momencie część aplikacji zaczyna się od polecenia załadowania rejestru ZL.
Funkcja konwersji liczby (stanu licznika) na jej reprezentację na wyświetlaczu działa w następujący sposób. W
pamięci programu mikrokontrolera zdefiniowano tablicę stałych ( wzorce ), uszeregowanych w taki sposób, że
wzorzec na początku tablicy odpowiada liczbie „0”, następny liczbie „1”, następny liczbie „2” i tak aż do „9”.
Tablicę umieszcza się w pamięci przy pomocy dyrektywy kompilatora .org i definiuje jej elementy po dyrektywie
.db <lista bajtów rozdzielonych przecinkami> . Polecenia:
ldi ZL,low(wzorce<<1)
ldi ZH,high(wzorce<<1)
powodują załadowanie do rejestru Z (jest to rejestr o długości 2-bajtów) adresu początku tablicy wzorce w
pamięci programu mikrokontrolera. W czasie ładowania, ze względu na sposób działania używanej dalej
instrukcji lpm , niezbędne jest przesunięcie adresu o jeden bit w lewo. Powoduje to zapis wzorce<<1 .
J.Bogusz „AVR Asembler – Licznik”
STRONA 1/3
305452984.001.png
http://www.easy-soft.tsnet.pl/
;Licznik binarny z wyświetleniem wartości na wyświetlaczu
;7-segmentowym LED TDSY3150 (użycie pojedynczej cyfry)
.include "8515def.inc"
.def temp = R16
.org 0
;---------------------------------------------
;wektory obsługi przerwań
;---------------------------------------------
rjmp RESET
;External Interrupt 0
reti
;External Interrupt 1
reti
;T/C1 Capture Event
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:
;ustawienie wskaźnika stosu
out SPL,temp
ldi temp,high(RAMEND)
out SPH,temp
;konfiguracja reakcji na przerwanie od wejścia INT0
ldi temp,(1<<INT0)
;ustawienie bitu odpowiedzialnego za akceptcję
out GIMSK,temp
;przerwania INT0 w rejestrze GIMSK
;nastawa "wrażliwości" przerwania
ldi temp,$03
;opadające zbocze na INT0 będzie generować
out MCUCR,temp
;przerwanie
;konfiguracja portu D
clr temp
;w tym przykładzie wszystkie linie portu D
out DDRD,temp
;pracują jako wejściowe
out PORTD,temp
;teraz do linii portu D dołączamy rezystory
;konfiguracja portu A
out DDRA,temp
;port A jako wyjściowy (temp zawiera $FF)
;wyświetlenie cyfry "0"
ldi ZL,low(wzorce<<1) ;załadowanie do rejestru Z adresu tablicy w ROM
ldi ZH,high(wzorce<<1) ;adres może być 2-bajtowy
lpm
;załadowanie do R0 wzorca cyfry z ROM (cyfra 0)
;temp będzie licznikiem
clr temp
;zezwolenie na przyjmowanie przerwań
sei
;główna pętla programu
loop:
rjmp loop
;program główny "kręci się" w pętli i oczekuje na
;przerwania od INT0
;---------------------------------------------
;obsługa przerwania od INT0
;---------------------------------------------
IRQ_Int0:
inc temp ;zwiększenie wartości temp o 1
cpi temp,10 ;porównaj zawartość zmiennej temp z liczbą 10
breq IRQ_Int0_Skip_Reti ;skocz, jeśli wartość jest równa 10
rjmp IRQ_Int0_Disp
;powrót z obsługi przerwania
IRQ_Int0_Skip_Reti:
ldi temp,0
;zerowanie zmiennej temp
IRQ_Int0_Disp:
;rejestr Z jest indeksem do wzorców cyfr w pamięci ROM
clr R0
;zerowanie R0-posłuży do dodania ew.przeniesienia
J.Bogusz „AVR Asembler – Licznik”
STRONA 2/3
rjmp IRQ_Int0
;po Reset
ldi temp,low(RAMEND)
ser temp
;zasilające pull-up (wewnętrzne)
out PORTA,R0
;wyprowadzenie wzorca przez port A
305452984.002.png
http://www.easy-soft.tsnet.pl/
ldi ZL,low(wzorce<<1) ;adres w ROM może być 2-bajtowy,należy uwzględnić
ldi ZH,high(wzorce<<1) ;młodszy i starszy bajt adresu
add ZL,temp
;do indeksu dodajemy wartość temp-to będzie
adc ZH,R0
;wartość przesunięcia w tablicy
out PORTA,R0
;załadowanie do R0 bajtu (wzorca cyfry) z ROM
reti
;definicje wzorców cyfr dla wyświetlacza LED, "0" na pozycji bitu odpowiada
;zaświeceniu segmentu, "1" jego zgaszeniu
wzorce:
.db
$82,$E7,$2A,$23,$47,$13,$12,$A7,$02,$03
Listing 1. Realizacja licznika dekadowego z wyświetlaniem wartości na wyświetlaczu LED.
Rozkaz lpm służy do odczytu struktur zawierających stałe i umieszczonych w pamięci programu. Adres bajtu
stałej musi być umieszczony w rejestrze Z. Wybierany jest przez 15 najstarszych bitów adresu, bit najmłodszy
decyduje o tym czy odczytywany jest młodszy, czy starszy bajt słowa programu. Instrukcja lpm umieszcza
odczytany bajt stałej w rejestrze r0. Wartość licznika (zmiennej temp ) wykorzystywana jest jednocześnie jako
offset indeksu tablicy. Dodanie do adresu zawartego w Z wartości 0, 1, 2, ...9 powoduje, że rejestr Z będzie
zawierać adres wzorca do wyświetlenia dla kolejno wymienionych liczb. Wybieraniem wzorców z tablicy zajmuje
się ciąg poleceń umieszczonych w obsłudze przerwania INT0. Ponieważ adres stałej z pamięci ROM jest
dwubajtowy, operacja dodania do adresu początku wartości licznika (zmiennej temp ) również wykonywana jest
dla 2 bajtów. W zestawie rozkazów AT90S8515 brak jest takiego, który dodaje stałą z tzw. przeniesieniem do
wartości rejestru. W związku z tym funkcję stałej pełni rejestr R0, wyzerowany przed wykonaniem operacji
dodawania tak, aby dodane zostało wyłącznie przeniesienie. To ważne, aby zasadę tą zrozumieć przy nauce
programowania w języku asembler. Dlatego też jeszcze kilka słów wyjaśnienia.
Mikrokontroler dodając dwie 1-bajtowe wartości może przeprowadzić operację arytmetyczną również wówczas,
gdy długość wyniku przekracza rozmiar rejestru. Jest to możliwe dzięki istnieniu wskaźnika przeniesienia, który
przyjmuje wartość logiczną 1 wówczas, gdy wynik przekracza pojemność rejestru przechowującego wynik
operacji arytmetycznej. Dla przykładu przytoczę jeden ze skrajnych przypadków: dodawane są do siebie dwie
wartości $FF szesnastkowo (255 dziesiętnie): $FF + $FF = $1FE (dziesiętnie: 255 + 255 = 510)
Wynik operacji nie jest jednym bajtem – jest dwubajtowy. Nie sposób więc zapisać go do rejestru o pojemności
1 bajtu. Jak łatwo jednak zauważyć, wartość starszego bajtu będzie co najwyżej równa 1. Potrzebny jest więc
faktycznie pojedynczy bit na sygnalizację przepełnienia. W większości mikrokontrolerów nosi on oznaczenie C
lub CY (z ang. Carry) i nazywa się flagą przeniesienia (również flagą C).
Aplikacja licznika jest bardzo mała i umieszczona w pamięci od adresu 0. Adres tablicy będącej wykazem
wzorców, umieszczonej za kodem programu, ma więc wartość jednobajtową. Praktycznie nie zdarzy się
sytuacja, w której będzie istnieć konieczność wykonania działania na 2 bajtach adresu. Ale teoretycznie może
zdarzyć się sytuacja, w której adres tablicy po dodaniu offsetu przekroczy rozmiar jednego bajtu lub tablica
zostanie przesunięta na koniec pamięci programu. Może więc zaistnieć konieczność wykonania działania na
wartości dwubajtowej.
Rozkaz dodawania add zawsze ustawia lub zeruje bit przeniesienia w zależności od długości liczby – wyniku. Bit
przeniesienia dodawany jest przez polecenie adc tworzące kompletną operację dodawania liczby dwubajtowej.
Najlepszą ilustracją będzie poniższy fragment aplikacji.
clr R0 ;załadowanie wartości 0 do rejestru R0
ldi ZL,low(wzorce<<1) ;załadowanie do rej.Z 2-bajowego adresu tablicy w pamięci
ldi ZH,high(wzorce<<1) ;stałej (programu) mikrokontrolera
add ZL,temp
;do młodszego bajtu adresu dodaję stan licznika będący
;jednocześnie wskazaniem na wzorzec do wyświetlenia
adc ZH,R0
;dodanie do starszego bajtu adresu wartości bitu
;przeniesienia
Myślę, że komentarze umieszczone obok instrukcji są wystarczające do zrozumienia zasady działania.
Prześledźmy jeszcze jak zachowa się program, gdy adres tablicy w ROM będzie miał wartość na przykład $0FA a
wartość zmiennej temp będzie równa 7.
clr R0 R0 = $00
add ZL,temp ZL = $FA+7 = $01 + (C = 1)
adc ZH,R0 ZH = $00 + (C=1) = $01
Po realizacji wyżej wymienionej sekwencji rozkazów, rejestr Z będzie zawierać wartość $0101, co jest
prawidłową wartością adresu dla cyfry 7 i początku tablicy pod adresem $00FA. Warto wspomnieć, że dla
potrzeb pewnych mniej zaawansowanych operacji, istnieje rozkaz adiw , dodający wartość bezpośrednią do
wartości rejestru dwubajtowego. Polecenie to automatycznie uwzględnia przeniesienie.
Jacek Bogusz
jacek.bogusz@easy-soft.tsnet.pl
J.Bogusz „AVR Asembler – Licznik”
STRONA 3/3
lpm
;wyprowadzenie wzorac przez port A
305452984.003.png 305452984.004.png
Zgłoś jeśli naruszono regulamin