|
|
Przykład 2 - Układ czasowy
Po naciśnięciu przycisku S1 kropka wyświetlacza zapala się na ok. 1 sekundę.
Algorytm działania programu przedstawiono na poniższym rysunku :

Kod źródłowy zamieszczony jest poniżej :
|
; Kurs asemblera mikrokontrolerów
AVR
;
; Przykład 2 - Układ czasowy
.include "2313def.inc"
.def acc = r16 ; nadanie rejestrowi r16 nazwy symbolicznej
.cseg
.org 0x00
ldi acc, 0b11111111 ; załaduj
do acc liczbę 255 (0xff)
out DDRB, acc ; wpisanie do DDRB samych jedynek
; powoduje ustawienie pinów jako wyjście
out PORTB, acc
ldi acc, 0b1111100 ;
out DDRD, acc ; piny D0 i D1 są ustawione jako wejścia
; pozostałe jako wyjścia
ldi r16, 0b1110111
out PORTD, acc
ldi acc, 127 ;
out SPL, acc ; ustawienie wskaˇnika stosu na 127
sprawdz_klawisze:
sbis PIND, 0 ; jeśli przycisk S1 nie jest wciśnięty
; to pomiń następną instrukcję
rcall led ; w przeciwnym wypadku wywołaj procedurę
; zapalającą diodę
rjmp sprawdz_klawisze ; powróć na początek sprawdzania klawiszy
led:
cbi PORTB, 7 ; zapal kropkę wyświetlacza
ldi acc, 250 ; załaduj do acc czas opóˇnienia
rcall waitms ; i wywołaj procedurę opóˇniającą
rcall waitms ; czterokrotne wywołanie opóˇnienia
rcall waitms ; 250ms da w sumie opóˇnienie ok 1s
rcall waitms ;
sbi PORTB, 7
ret
; Przybliżone czasy opóźnień
są podane dla
; rezonatora 4MHz
.def licz1 = r20
.def licz2 = r21
.def licz3 = r22
waitms:
mov licz3, acc ; ustaw czas opóĽnienia
; powtórz n razy pętlę L,
; co da opóˇnienie ok. n * 1 ms
L:
; powtórz 10 razy pętlę L0,
; co da opóĽnienie ok 1ms
ldi licz2, 10
L0:
; powtórz 100 razy pętlę L1,
; co da opóĽnienie ok. 100 us
ldi licz1, 100
L1:
nop ; 1 cykl
dec licz1 ; 1 cykl
brne l1 ; 2 cykle
; koniec pętli L1
dec licz2
brne l0
; koniec pętli L0
dec licz3
brne L
; koniec pętli L
ret
|
Pierwsza część programu składa się z instrukcji poznanych
w przykładzie wcześniejszym, więc nie będę ich tutaj ponownie opisywał.
Instrukcja MOV (Copy registers) kopiuje zawartość
jednego rejestru do drugiego. Zawartość rejestru ˇródłowego nie ulega
zmianie.
| Składnia rozkazu |
Operandy |
Licznik rozkazów: |
| (i) MOV Rd,Rr |
0 <= d <=31, 0 <= r <= 31 |
PC <- PC + 1 |
Kod operacji :
0010 11rd dddd rrrr
Komentarz:
Wartość opóˇnienia przekazujemy przez rejestr r16 i kopiujemy jego zawartość
do r22, czyli do licznika pętli. Takie rozwiązanie zostało zastosowane,
w celu zachowania zawartości rejestru r16. Pozwoli to na kilkukrotne wywołąnie
procedury opóˇniającej o tą samą wartość opóˇnienia bez konieczności każdorazowego
ładowania czasu opóˇnienia.
Instrukcja NOP (No operation) nie wykonuję żadnych
czynności poza zwiększeniem zawartości licznika rozkazów o 1. Instrukcja
jest wykorzystywana do generowania opóˇnień czasowych.
| Składnia rozkazu |
Operandy |
Licznik rozkazów: |
| (i) NOP |
brak |
PC <- PC + 1 |
Kod operacji :
0000 0000 0000 0000
Komentarz:
Pętla L1 ma wnosić opóˇnienie 100us. Ponieważ cykl rozkazowy przy częstotliwości
taktowania mikrokontrolera równej 4MHz wynosi 250ns jeden przebieg pętli
musi wnieść opóˇnienie 1us, czyli 4 cykli. Ponieważ instrukcje DEC r20
i BRNE L1 razem trwają 3 cykle (przy niespełnieniu waruknu instrukcji
BRNE) to za pomocą intrukcji NOP wstawiamy ten jeden brakujący cykl.
Instrukcja BRNE (Branch if not equal) wykonuje skok
warunkowy, jeśli flaga zera (Z) jest wyzerowana.
| Składnia rozkazu |
Operandy |
Licznik rozkazów: |
| BRNE k |
-64 <= k <= +63 |
PC <- PC + k + 1
PC <- PC + 1, jeśli warunek niespełniony
|
Kod operacji:
1111 01kk kkkk k001
Instrukcja DEC (Decrement) zmniejsza o jeden zawartość
rejestru Rd.
| Składnia rozkazu |
Operandy |
Licznik rozkazów: |
| DEC Rd |
0 <= d <= 31 |
PC <- PC + 1 |
Kod operacji:
1001 010d dddd 1010
Komentarz:
Instrukcja ta jest wykorzystana do zmniejszania zawartości licznika pętli.
Ponieważ znienia stan flagi Z możliwe jest wykonanie po niej instrukcji
BRNE
Program ten napisany w asemblerze zajmuje 62 bajty (31 słów) pamięci programu.
Program napisany w Bascomie realizujący tą samą funkcję zajmuje 174 bajty
(87 słów).
|
|