Technika cyfrowa
Laboratorium
Temat: System przerwań. Przerwania od liczników i zewnętrzne.
Paweł Wańtowski 16.V.2006, Wrocław
Grzegorz Smychowski
Zadania do wykonania
Zadanie 1.
W zadaniu 1. należało utworzyć program, którego zadaniem jest generowanie opóźnień czasowych o zadanym czasie t (np. t1 oraz t2), przy czym program ten ma wykorzystywać licznik T0 lub T1. Napisanie takiego programu wymaga znajomości działania układów czasowo-licznikowych mikroprocesora 8051. Istotne jest, iż zawartość każdego licznika jest pamiętana na dwóch bajtach (dla T0: TH0-TL0 na rejestrach SFR 8Ch-8Ah, dla T1: TH1-TL1 na rejestrach SFR 8Dh-8Bh). Ważna jest też znajomość sposobu ustawiania rejestru specjalnego TMOD. Mając na względzie fakt, iż program ten ma zostać napisany z wykorzystaniem przerwań, należy wykorzystać polecenia SetB EAL do odblokowania systemu przerwań oraz SetB ETx do zezwolenia na przyjęcie przerwania od timera Tx.
Zadanie 2.
Zadanie to polegało na utworzeniu programu generującego przynajmniej 3 równoległe sekwencje o zadanych czasach THIGH i TLOW. Wizualizacja czasu trwania zadanych sekwencji może być dokonana z wykorzystaniem diod LED, zaś program może być w dużej mierze oparty na programie zrealizowanym na potrzeby zadania 1.
Zadanie 3.
Celem zadania 3. było utworzenie programu o funkcjonalności stopera. Program ma za zadanie mierzyć odstęp czasu zawarty pomiędzy naciśnięciem przycisków powiązanych z portami P3.2 oraz P3.3, a następnie wyświetlać tenże czas (w sekundach) na wyświetlaczu LCD.
Opis realizacji
ad. Zadanie 1.
Utworzony program, działający w nieskończonej pętli, musiał zostać wyposażony w odwołania do potrzebnych do zrealizowania zadania rejestrów specjalnych (nieodzowne było ustawienie odpowiedniego trybu pracy poprzez ustawienie poszczególnych bitów rejestru TMOD) i obsługę THx oraz TLx, odpowiedzialnych za czasy THIGH i TLOW zadawane wykorzystywanemu w zadaniu timerowi T1. Cykliczne generowanie opóźnienia czasowego jest zobrazowane poprzez zapalanie i gaszenie diody powiązanej z portem P1.0. Samo zapalanie i gaszenie realizowane jest w bardzo prosty sposób - następuje to poprzez zanegowanie stanu portu P1.0 poleceniem CPL. Odpowiednie ustawienie wartości TH1 oraz TL1 pozwala na generację impulsu czasowego o czasie trwania 50 ms. Dzięki odpowiedniemu wykorzystaniu przechowywanej w rejestrze R2 wartości 10 w pętli DJNZ zapalenie bądź wygaszenie diody trwa przez okres czasu równy 0.5 s. Dodatkowe komentarze zostały umieszczone w kodzie programu, który z kolei został umieszczony w listingu 1.
ad. Zadanie 2.
Tworzenie niniejszego programu pozwoliło wykorzystać wiedzę nabytą przy realizacji poprzedniego zadania oraz - częściowo - rozwiązania w nim zastosowane. Wygenerowanie trzech równoległych sekwencji nasunęło ideę umożliwienia deklaracji okresu stanu zapalenia i zgaszenia każdej z trzech wykorzystywanych diod podpiętych do portu P1 (jest to umożliwione poprzez deklarowanie w kodzie programu wartości ON1, OFF1, ON2, OFF2, ON3, OFF3). Wykonanie trzech odrębnych procedur obsługujących poszczególne diody pozwala operować nimi w prosty sposób, zaś przeniesienie ich obsługi poza główną procedurę START wpływa na przejrzystość kodu programu. Kod programu wraz z odpowiednimi komentarzami umieszczony został w listingu 2.
ad. Zadanie 3.
Zadanie miało polegać na utworzeniu stopera, czyli programu, który miałby odmierzać czas upływający pomiędzy naciśnięciami odpowiednich przycisków. Ze względu na chęć uproszczenia interfejsu zadania oraz nadania mu specyfiki prawdziwych stoperów, zdecydowaliśmy się na użycie przycisków P3.3 oraz P3.2. Należy dodać, iż dla ułatwienia obsługi wyświetlacza LCD skorzystaliśmy z utworzonej na wcześniejszych zajęciach biblioteki LCD.inc, implementujące podstawowe funkcje powiązane z obsługą wyświetlacza LCD. O ile kod programu wydaje się być poprawny, o tyle wystąpiły problemy z wyświetleniem zmierzonego wyniku na wyświetlaczu LCD, co jest dość dziwne uwzględniając fakt, iż analogiczny program wykorzystujący przerwania napisany przez nas na poprzednich zajęciach działał bez zarzutu. Możliwe, że złe funkcjonowanie programu było skutkiem problemów w funkcjonowaniu makiety ZD537, z jakimi napotkaliśmy się w końcowym okresie trwania laboratorium. Kod programu został umieszczony w listingu 3, zaś wykorzystywane w programie fragmenty biblioteki LCD.inc w listingu 4.
Uwagi końcowe
Wykonywane ćwiczenia pozwoliły utrwalić wiedzę dotyczącą działania timerów T0 oraz T1, a także generacji i pomiaru wybranych odcinków czasu.. Zrezygnowaliśmy z ustawiania rejestru TMOD przy pomocy masek zadawanych poleceniami ORL i ANL na korzyść prostszego i czytelniejszego wykorzystania polecenia MOV i bezpośredniego binarnego ustawienia wartości przypisanej rejestrowi TMOD. Bardzo istotny jest wniosek płynący z porównania programów implementujących timery i wykorzystujących przerwania z programami implementującymi timery i korzystającymi ze znaczników przepełnienia: wykorzystanie przerwań pozwala zaimplementować tę samą funkcjonalność w wygodniejszy dla programisty sposób. Przydatna okazała się również napisana wcześniej biblioteka podprogramów obsługujących wyświetlacz LCD. Niestety, w związku z problemami w funkcjonowaniu makiety ZD537 nie udało nam się wypełnić założeń wszystkich zadań przewidzianych do realizacji podczas zajęć laboratoryjnych. Listingi poszczególnych programów zostały umieszczone na stronach 3-6. Wykorzystane fragmenty usprawnionej przez nas biblioteki LCD.inc zostały zamieszczone na stronie 7.
Listing 1. Kod programu z zadania 1.
$nomod51 ; wylaczenie predefinicji rejestrow 8051
$include(reg517.inc) ; wlaczenie predefinicji rej. procesora 80537
CSEG AT 0000h
JMP START
ORG 0Bh ; adres przerwania od T0
MOV TH0, #03Ch ; ustawienie wartości poczatkowych
MOV TL0, #0AFh
DJNZ ACC, LOOP
CPL P1.0 ; zapal/zgas diode
MOV A, #10
LOOP:
RETI ;powrót z przerwania
ORG 100h
START:
MOV TMOD,#00000001b ; ustawienie rejestru TMOD
MOV TH0, #03Ch ; wpisanie wartości poczatkowych
MOV TL0, #0AFh
MOV A,#10 ; czas=10*50ms=0,5[s]
SETB TR0 ; start T0
SETB EAL ; odblokowanie systemu przerwań
SETB ET0 ; zezwolenie na przerwanie od T0
SJMP $
END
Listing 2. Kod programu z zadania 2.
;Lab5_Zad2_PW_GS_TC3
$NOMOD51 ; wylaczenie predefinicji rejestrow
$INCLUDE(reg517.inc) ; wlaczenie predefinicji rej. procesora 80537
CSEG AT 0000h
TH0_SET EQU 256-180 ; obliczenie wartosci poczatkowych
TL0_SET EQU 0
ON1 EQU 130 ; czas trwania zapalenia diody P1.0
OFF1 EQU 15 ; czas trwania zgaszenia diody P1.0
ON2 EQU 27 ; czas trwania zapalenia diody P1.1
OFF2 EQU 43 ; czas trwania zgaszenia diody P1.1
ON3 EQU 65 ; czas trwania zapalenia diody P1.2
OFF3 EQU 91 ; czas trwania zgaszenia diody P1.2
LJMP START
ORG 0BH ; adres procedury obslugi T0
MOV TH0, #TH0_SET ; wpisanie wartości poczatkowek TH
DEC R0
MOV A, R0
LCALL LED1 ; wezwanie procedury obslugujacej diode P1.0
DEC R1
MOV A, R1
LCALL LED2 ; wezwanie procedury obslugujacej diode P1.1
DEC R2
MOV A, R2
LCALL LED3 ; wezwanie procedury obslugujacej diode P1.2
RETI ; powrot z przerwania
LED1: ; procedury obslugujaca diode P1.0
JNZ K
CPL P1.0 ; zanegowanie stanu diody P1.0
JB P1.0, LED_ON1
MOV R0, #ON1 ; ustawienie czasu zapalenia diody P1.0
LJMP K
LED_ON1:
MOV R0, #OFF1 ; ustawienie czasu zgaszenia diody P1.0
K:
RET
LED2: ; procedury obslugujaca diode P1.1
JNZ K2
CPL P1.1 ; zanegowanie stanu diody P1.1
JB P1.1, LED_ON2
MOV R1, #ON2 ; ustawienie czasu zapalenia diody P1.1
LJMP K2
LED_ON2:
MOV R1, #OFF2 ; ustawienie czasu zgaszenia diody P1.1
K2:
RET
LED3: ; procedury obslugujaca diode P1.2
JNZ K3
CPL P1.2 ; zanegowanie stanu diody P1.2
JB P1.2, LED_ON3
MOV R2, #ON3 ; ustawienie czasu zapalenia diody P1.2
LJMP K3
LED_ON3:
MOV R2, #OFF3 ; ustawienie czasu zgaszenia diody P1.2
K3:
RET
START:
CPL P1.0 ; zanegowanie stanu diody P1.0
CPL P1.1 ; zanegowanie stanu diody P1.1
CPL P1.2 ; zanegowanie stanu diody P1.2
MOV R0, #ON1 ; przesuniecie do rejestrow okresow
MOV R1, #ON2 ; zapalenia kolejnych diod LED
MOV R2, #ON3
MOV TMOD, #00000001b ; ustawienie rejestru TMOD
MOV TH0, #TH0_SET ; wpisanie wartości poczatkowych
MOV TL0, #TL0_SET
SETB TR0 ; start T0
SETB EAL ; odblokowanie systemu przerwań
SETB ET0 ; zezwolenie na przerwanie od T0
SJMP $
END
Listing 3. Kod programu z zadania 3.
;Lab5_Zad3_PW_GS_TC3
$nomod51
$include(reg517.inc)
$include (lcd.inc)
ORG 0
LJMP PROG ; skok do procedury PROG
ORG 0Bh
LJMP PRZER ; skok do procedury PRZER
ORG 30h
PRZER:
INC B
RETI
PROG:
CALL initLCD ; wezwanie procedury inicjującej LCD
CALL LCDclear ; wezwanie procedury czyszczącej LCD
ORL TMOD,#09 ; ustawienie trybu pracy timera T0
SETB EAL ;odblokowanie systemu przerwań
SETB ET0 ;przerwanie od T0
POM:
MOV R0,#20h
CLR A ; czyszczenie zawartości akumulatora
MOV TL0,A
MOV TH0,A
MOV B,A
JB P3.3,$ ; obsluga przycisku uruchamiajacego stoper
SETB TR0 ; start pracy timera
JB P3.2,$ ; obsluga przycisku wylaczajacego stoper
CLR TR0 ; koniec pracy timera
MOV @R0,TL0
INC R0
MOV @R0,TH0
INC R0
MOV @R0,B ; przeksztalcenia wyniku w celu
MOV A,B ; poprawnego wyswietlenia go
MOV B,#15 ; na LCD
DIV AB
CALL putInt ; wezwanie procedury wyprowadzajacej czas na LCD
LJMP POM ; skok do procedury POM
END
Listing 4. Wykorzystywane na potrzeby zadania 3 fragmenty biblioteki LCD.inc.
#define INITDISP 0x38 ; LCD init (8-bit mode, 2-lines, 5x8 dots) ;Function Set
#define LCDON 0x0e ; LCD on, cursor on, blinking off ;Display ON/OFF ocntrol
#define CLEAR 0x01 ; LCD display clear
LCDcntrlWR MACRO X
MOV DPTR,#LCDcontrol
MOV A, X
MOVX @DPTR,A
ENDM
put_char MACRO
PUSH ACC
CALL busy
MOV DPTR,#LCDdataWR
POP ACC
MOVX @DPTR,A
ENDM
initLCD:
LCDcntrlWR #INITDISP
LCDcntrlWR #CLEAR
LCDcntrlWR #LCDON
RET
putInt: ; wyswietlana liczba w A
PUSH ACC
MOV B,#10
DIV AB
MOV B,#10
DIV AB
ORL A,#00110000b
CALL putChar
MOV A,B
ORL A,#00110000b
CALL putChar
POP ACC
PUSH ACC
MOV B,#10
DIV AB
MOV A,B
ORL A,#00110000b
CALL putChar
POP ACC
RET
putChar: ;wyswietlany znak nalezy zaladowac do A
put_char
RET
LCDClear:
LCDcntrlWR #CLEAR
RET
2