mikrokontrolery.net

 

   

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).

 

 

 

 

 

 

 

 

 

 

 
 
 
 

(c) 2004-2008 Radosław Kwiecień
Polityka prywatności