S. Jemioło B. Jakubiec
G. Kulig Ł. Król
Klasa VgT
Ćwiczenie nr 7
TEMAT: KLAWIATURA PRZEGLĄDANA SEKWENCYJNIE.
Cel ćwiczenia:
Poznanie sposobów odczytu danych z portu mikrokontrolera, czyli odczyt pojedynczej linii na przykładzie odczytu stanu klawiatury przeglądanej programowo.
Wiadomości wstępne:
Porty mikrokontrolera 8051 są to tzw. porty pseudo-dwukierunkowe. Jeżeli pełnią one rolę portów wyjściowych, to po prostu należy do nich wpisać odpowiednie dane. W ten sposób poszczególne linie są ustawiane w stan 0 lub 1. Jeżeli jednak wybrane linie mają spełniać funkcję linii wejściowych, to należy ustawić je w stan 1.
Jak z tego widać, można indywidualnie decydować o tym, które linie z portu są liniami wejściowymi. Port mikrokontrolera został tak zbudowany, aby linia ustawiona w stan 1 mogła być z zewnątrz przestawiona na 0. Ponieważ po sygnale RESET wszystkie porty mikrokontrolera są ustawione na 1, mogą d razu pełnić funkcję wejść.
W systemie DSM-51 część linii portu P3 jest wykorzystywanych jako linie wejściowe. Między innymi linia 5 (P3.5) jest wykorzystywana do odczytu stanu klawiatury wyświetlacza 7- segmentowego.
W tym sposobie podłączenia o tym, który klawisz można aktualnie odczytać przez linię P3.5 decyduje bufor wyjściowy podłączony do szyny mikrokontrolera. Jest to ten sam bufor, który decyduje o wyborze wskaźnika. Wynika z tego, że jeżeli aktualnie wyświetlane są dane na pierwszym wskaźniku, to jednocześnie można odczytać stan klawisza 1-[Enter].
Bit wyboru wskaźnika |
0 |
1 |
2 |
3 |
4 |
5 |
6
|
Odczytywany klawisz |
[Enter] |
[Esc] |
[→] |
[↑] |
[↓] |
[←] |
|
Tabela przedstawia sposób przyporządkowania wszystkich klawiszy odpowiednim bitom wpisanym do bufora wyboru wskaźnika.
PRZYKŁAD 7.1
ODCZYT POJEDYNCZEJ LINII
LED EQU P1.7
KEY EQU P3.5 ;odczyt klawiatury
;Stałe używane w programie
KEY_COD EQU 00001001B ;wybrane klawisze - 1i4
LJMP START
ORG 100H
START:
MOV R0,#CSDS ;adres wyboru klawisza
MOV A,#KEY_COD
MOVX @R0,A ;wpisz wybrane klawisze
LOOP:
MOV C,KEY ;czytaj stan klawiszy
CPL C ;neguj
MOV LED,C ;zapal diodę TEST gdy klawisz jest naciśnięty
SJMP LOOP
W przykładzie 7.1 odczytanie stanu linii P3.5 następuje rozkazem MOV. Rozkaz ten wpisuje do bitu C stan linii P3.5. Stan odczytywany z linii P3.5 jest negowany i wystawiany na linię P1.7 (LED). W ten sposób stan 1 z klawiatury (naciśnięty klawisz) powoduje wpisanie 0 do bitu P1.7 (LED świeci). Dzięki zapętleniu tych rozkazów stan klawiatury jest odwzorowywany na diodzie TEST.
Do bufora wyboru wskaźnika została wprowadzona stała zawierająca dwie jedynki - odpowiadające klawiszom 1 i 4. Jak można zaobserwować po uruchomieniu programu, właśnie na te klawisze reaguje program, Jeżeli zachowana jest stała wartość wpisana do bufora wyboru wskaźnika, to w programie nie można rozróżnić, który klawisz jest naciśnięty.
PRZYKŁAD 7.2
ODCZYT KLAWISZA
LED EQU P1.7
KEY EQU P3.5 ;odczyt klawiatury
;Stałe używane w programie
KEY_COD EQU 00001001B ;wybrane klawisze - 1i4
LJMP START
ORG 100H
START:
MOV R0,#CSDS ;adres wyboru klawisza
MOV A,#KEY_COD
MOVX @R0,A ;wpisz wybrane klawisze
LOOP_NO:
JNB KEY,LOOP_NO ;czekaj na naciśnięcie klawisza
CPL LED ;neguj stan diody TEST przy naciśnięciu klaw.
LOOP_YES:
JB KEY,LOOP_YES ;czekaj na zwolnienie klawisza
SJMP LOOP_NO ;powrót do pętli czekania na klawisz
W przykładzie 7.2 realizowana jest reakcja programu ma klawisz naciśnięty lub zwolniony. Stan klawiszy jest odczytywany przy wykorzystaniu do tego rozkazów skoków warunkowych. Rozkaz skoku warunkowego może być wykonany na dwa sposoby, w zależności od spełniania warunków. Jeżeli warunek jest spełniony, następuje skok do etykiety określonej w rozkazie. W przeciwnym razie, program przechodzi do realizacji następnego rozkazu.
W rozkazie JB (Jump if Bit) warunkiem jest stan bitu określonego w rozkazie. Jeżeli bit jest równy 1, to warunek jest spełniony i następuje skok do określonej etykiety. W rozkazie JNB (Jump if Not Bit) spełnienie warunku następuje, gdy bit jest równy 0.
Program jest realizowany w dwóch pętlach. W pierwszej (LOOP-NO) program jest realizowany w czasie, gdy klawisz nie jest naciśnięty. Jeżeli klawisz zostanie naciśnięty, to program wychodzi z pętli. Sygnalizowane jest to diodą TEST. W drugiej pętli (LOOP-YES) program realizowany jest w czasie, gdy klawisz jest naciśnięty. Trwa to do zwolnienia klawisza. Gdy to nastąpi, program znowu wraca do pętli pierwszej.
Po uruchomieniu programu można zaobserwować, że nie zawsze działa tak jak powinien ( mruganie diody), dzieje się to na skutek drgań styków w klawiaturze, drgania są odczytywane jako kolejne naciśnięcia, aby temu zapobiec należy wprowadzić pewne opóźnienie w pętlach odczytujących stan klawiatury.
PRZYKŁAD 7.3
ELIMINACJA DRGAŃ STYKÓW
LED EQU P1.7
KEY EQU P3.5 ;odczyt klawiatury
KEY_COD EQU 00001001B ;wybrane klawisze-1i4
LJMP START
ORG 100H
START:
MOV R0,#CSDS ;adres wyboru klawisza
MOV A,#KEY_COD
MOVX @R0,A ;wpisz wybrane klawisze
LOOP_NO:
JNB KEY,LOOP_NO ;czekaj na naciśnięcie klawisza
MOV A,#10 ;eliminacja drgań styków
LCALL DELAY_MS
JNB KEY,LOOP_NO ;czy nadal naciśnięty
CPL LED ;neguj stan diody TEST przy naciśnięciu klaw.
LOOP_YES:
JB KEY,LOOP_YES ;czekaj na zwolnienie klawisza
MOV A,#10 ;eliminacja drgań styków
LCALL DELAY_MS
JB KEY,LOOP_YES ;czy klawisz zwolniony
SJMP LOOP_NO ;powrót do pętli czekania na klawisz
Przykład 7.3 jest modyfikacją poprzedniego programu, który ma poprawioną część programu odczytującego stany klawiatury. Program dzięki wprowadzonemu opóźnieniu nie powoduje migotania diody - podprogram DELAY_MS.
PRZYKŁAD 7.4
ODCZYT KLAWIATURY
SEG_ON EQU P1.6 ;włączenie wyświetlacza 7-segm.
LED EQU P1.7
KEY EQU P3.5 ;odczyt klawiatury
;Pamięć wewnętrzna RAM
DISPLAY EQU 30H
KEY_LAST EQU DISPLAY+6
LJMP START
ORG 100H
START:
CLR A
MOV DISPLAY,A ;wpisz 0 do pamięci
MOV DISPLAY+1,A ;danych wszystkich
MOV DISPLAY+2,A ;wskaźników
MOV DISPLAY+3,A
MOV DISPLAY+4,A
MOV DISPLAY+5,A
MOV DISPLAY+6,A
LOOP_DISP: ;ustaw dane do wyśw. na wskaźniku 1
MOV R0,#DISPLAY ;adres pobierania kodów
MOV R2,#7 ;licznik - liczba wskaź.
MOV R3,#00000001B ;wybór wskaźnika - kod 1 z 8
LOOP:
SETB SEG_ON ;wyłącz poprzedni wskaźnik
MOV R1,#CSDS ;adres wyboru wskaźnika
MOV A,R3 ;nr wskaźnika (1z8)
MOVX @R1,A ;wpisz wybrany wskaźnik
MOV R1,#CSDB ;adres danych wskaźnika
MOV A,@R0 ;dane wskaźnika
CJNE R3,#01000000B,SEG ;czy 7 wskaźnik
SJMP LEDS ;tak-diody świecące
;nie ma zamiany na kod
SEG:
LCALL GET_COD7 ;zamiana cyfry na kod
LEDS:
MOVX @R1,A ;wpisanie kodu zapalanych seg do buforu danych wskaźnika
CLR SEG_ON ;włączenie wskaźnika
MOV C,KEY ;wstępny odczyt klawisza
MOV A,#1 ;odczekanie 1ms-świecenie
LCALL DELAY_MS ;jednego wskaźnika
JC KEY_ON ;kontrola jednoznaczności
JB KEY,KEY_END ;odczytu klawisza
KEY_OFF:
MOV A,R3 ;klawisz zwolniony
CPL A
ANL KEY_LAST,A ;zeruj odpowiedni bit
SJMP KEY_END
KEY_ON:
JNB KEY,KEY_END
MOV A,R3 ;klawisz naciśnięty
ANL A,KEY_LAST
JNZ KEY_END ;klawisz był naciśnięty bez reakcji
MOV A,R3 ;klawisz był zwolniony
ORL KEY_LAST,A ;ustaw odpowiedni bit
INC @R0 ;zwiększ licznik nac.-liczbę na odpowiednim wskaźniku
KEY_END:
MOV A,R3
RL A ;numeru następnego
MOV R3,A ;wskaźnika (kod 1 z 8)
INC R0 ;adres danych następnego wskaźnika
DJNZ R2,LOOP ;kolejne świecenie
;siedmiu wskaźników
SJMP LOOP_DISP ;zacznij od wskaźnika 1
;Podprogram zamienia cyfrę na kod 7-segmentowy
GET_COD7:
ANL A,#0FH ;tabela kodów 0..15
INC A ;pomiń rozkaz RET
MOVC A,@A+PC ;pobierz kod
RET
COD_7SEG:
DB 03FH ;kod znaku 0
DB 006H ;kod znaku 1
DB 05BH ;kod znaku 2
DB 04FH ;kod znaku 3
DB 066H ;kod znaku 4
DB 06DH ;kod znaku 5
DB 07DH ;kod znaku 6
DB 007H ;kod znaku 7
DB 07FH ;kod znaku 8
DB 06FH ;kod znaku 9
DB 077H ;kod znaku A
DB 07CH ;kod znaku b
DB 039H ;kod znaku C
DB 05EH ;kod znaku d
DB 079H ;kod znaku E
DB 071H ;kod znaku F
Przykład 7.4 swoim działaniem umożliwia różne reakcje programu w zależności od tego, który klawisz jest naciśnięty, należy odczytywanie stanu klawiszy wpleść w program wyświetlania na wyświetlaczu 7-seg.
Pobranie kodu 7-seg. Realizowane jest za pomocą instrukcji MOVC. Literka C oznacza, iż rozkaz ten dotyczy pamięci programu (ang. Code). Odpowiednie dane zostaną odczytane przez szynę systemową z zewnętrznej pamięci programu. Rozkaz MOVC A, @A+PC oznacza, że do akumulatora załadowana zostanie zawartość komórki, adresowana przez licznik programu, modyfikowany przez poprzednią wartość akumulatora - adresowanie indeksowe.
W pętli LOOP następuje wymiana zawartości bufora wyboru wskaźnika i bufora danych wskaźnika, tak jak było to przedstawione w lekcji 6. Następnie program przechodzi do odczytu stanu klawiszy. Najpierw stan klawisza zapamiętywany jest w bicie przeniesienia C, a następnie jest realizowane odczekanie czasu 1 ms. Po tym czasie ponownie jest odczytywany stan klawisza - tym razem za pomocą skoków warunkowych.
W programie została zdefiniowana komórka pamięci KEY_LAST, w której zapamiętywany jest ostatni stan klawiszy. Jedynka na odpowiednim bicie oznacza, że w poprzednim przebiegu pętli klawisz był naciśnięty, natomiast 0 - nie.
Fragment programu od etykiety KEY_ON rozstrzyga reakcje programu, jeśli klawisz jest naciśnięty. Wykorzystując wartość rejestru R3 (w kodzie 1 z 8) program sprawdza, czy poprzednio odpowiedni klawisz też był naciśnięty. Program reaguje jedynie wtedy, gdy poprzednio klawisz nie był naciśnięty. Reakcja programu polega na ustawieniu odpowiedniego bitu w komórce KEY_LAST oraz na zwiększeniu o 1 zawartości komórki wyświetlanej na danym wskaźniku. W ten sposób na wskaźnikach liczona jest liczba naciśnięć poszczególnych klawiszy.
Fragment programu od etykiety KEY_OFF reaguje na zwolnienie klawisza. Tutaj reakcja jest znacznie prostsza - na podstawie wartości w rejestrze R3 następuje wyzerowanie odpowiedniego bitu w komórce KEY_LAST. Nie zachodzi tutaj nawet konieczność kontrolowania stanu, w jakim był ten bit poprzednio. W wyżej przedstawionym przykładzie komórka KEY_LAST została tak umiejscowiona w pamięci (względem komórki dispaly), że oprócz funkcji przy testowaniu klawiszy, jej zawartość wyświetlana jest na LEDACH stanowiących siódmy wskaźnik.
Wnioski:
Istniejące w mikrokontrolerze 8051 porty użytkownik może wykorzystywać jako wejściowe lub wyjściowe poprzez odpowiednie modyfikacje stanów tych portów. Dzięki temu możliwe jest odczytywanie klawiatury mikrokontrolera.