EdW 2003/08 – strona 50

Transkrypt

EdW 2003/08 – strona 50
+
Klawiatura do mikrokontrolera,
czyli osiem przycisków w jednym
2673
Do czego to służy?
Gdy budujemy system mikroprocesorowy,
który w założeniach ma być obsługiwany
przez człowieka, do przekazywania mu informacji zwykle używamy klawiatur. Są to klawiatury dołączone wprost do wyprowadzeń
mikroprocesora i masy lub plusa zasilania lub
też matrycowe. W obu przypadkach zajmują
one niemało wyprowadzeń układu, co często
jest poważnym problemem. Zwłaszcza
w 89C2051, 90S2313 lub miniaturowych
AVR-ach (np. 90S2343, 90S1200). Niekiedy
brakuje nam wyprowadzeń. Prezentowany
układ rozwiązuje powyższe problemy, gdy
potrzebna jest klawiatura o ośmiu lub mniej
przyciskach. Do jego połączenia z procesorem wystarczy jedno wyprowadzenie. Układ
na swoim wyjściu wytwarza przebieg prostokątny niosący informację o numerze wciśniętego przycisku. Jest on łatwy do zdekodowania za pomocą dowolnego procesora. Ogromną zaletą układu jest jego bardzo niska cena
oraz to, że w spoczynku w ogóle nie pobiera
prądu, z wyjątkiem liczonych w nanoamperach prądów polaryzacji wejść CMOS i różnych prądów upływu. Pomiar tego prądu za
pomocą mikroamperomierza cyfrowego
o rozdzielczości 1µA nie spowodował jakiejkolwiek reakcji miernika, nawet na tej najmniej znaczącej pozycji – a więc prąd pobierany w spoczynku jest dużo mniejszy od
1µA! Pobór w trakcie pracy wynosi ok.
650µA i może być zmniejszony, jeśli zajdzie
taka potrzeba poprzez zwiększenie wartości
rezystorów R2,R3 i R6, które są w modelu
stosunkowo małe. Cechy te pozwalają na zasilanie bateryjne. I tu ujawnia się kolejne zastosowanie opisywanego modułu – dodając
jakikolwiek generator częstotliwości nośnej
(choćby na 4047 lub 555 CMOS), możemy
zbudować taniutki i prosty pilot zdalnego
50
sterowania, przeznaczony do współpracy
z mikrokontrolerem. Kolejną zaletą jest wyjście typu otwarty kolektor.
Jak to działa?
Schemat ideowy przedstawiony jest na rysunku 1. Jak widać, całość zrealizowałem
z użyciem dwóch prostych układów CMOS
i garstki elementów. W stanie spoczynku
wszystkie przyciski są rozwarte, U1 jest wyzerowany i na jego wyjściu Q0 występuje
stan wysoki. Tranzystor T2 jest zatkany a generator z bramką U2A nie pracuje. Na nóżce
11 U2 jest stan niski i T1 jest zatkany. Wciśnięcie któregokolwiek z przycisków spowoduje podanie stanu niskiego na wejście RST
układu U1 oraz otwarcie T2. Drgania występujące na początku nie będą przeszkadzać,
gdyż obwód opóźniający R4C2 nie pozwoli
na uruchomienie generatora z bramką
U2A, zanim drgania te nie ustąpią. Gdy już
tak się stanie, generator ten zaczyna pracować, wytwarzając przebieg prostokątny o częstotliwości ok. 1kHz. Wraz z wystąpieniem
pierwszego zbocza narastającego stan wysoki
zniknie z wyjścia Q0 U1, bramka U2B otworzy bramkę U2C i na wyjściu układu (kolektor T1) pojawi się zanegowany przebieg
z nóżki 3 U2 – za stan wysoki uznaję tu stan
zatkania T1, wszak jego kolektor będzie zawsze podciągnięty do plusa zasilania sterowanego układu mikroprocesorowego.
Przyjmijmy na początek następującą umowę: słowem impuls będę określał połowę
okresu generatora, czyli występowanie tam
Rys. 1 Schemat ideowy
E l e k t ro n i k a d l a Ws z y s t k i c h
E l e k t ro n i k a d l a Ws z y s t k i c h
A
M
A
L
K
E
R
·
A
M
A
L
K
E
R
·
A
M
A
R
E
K
L
do sytuacji, w której analizowana seria przerwana byłaby w połowie przez puszczenie
przycisku – dotyczy to zwłaszcza szybkich
styków popularnych microswitchów.
Przykładową, wypróbowaną w praktyce na
2051, procedurę realizującą powyższe założenia w języku C przedstawia Listing 1. Funkcja Wait_for_long, jak sama nazwa wskazuje,
czeka na długi impuls. Zwraca 0, gdy był to
„dobry” impuls, czyli taki, po którym wciąż
nadchodzą krótkie impulsy; zwraca 1, jeśli impuls ten trwa zbyt długo – jest wynikiem puszczenia przycisku. Za argument przyjmuje
wskaźnik do zmiennej w której umieszcza
wynik, czyli liczbę krótkich impulsów jakie
wystąpiły od momentu wywołania tej funkcji
do najbliższego długiego impulsu. W funkcji
main jest przykład wykorzystania: pierwsze
wywołanie Wait_for_long służy zignorowaniu
pierwszej serii, po drugiej w zmiennej numer
jest numer wciśniętego przycisku (0...7). Po
wykorzystaniu tej wartości do określonego celu program czeka aż zwróci ona 1 – tym samym czeka na puszczenie przycisku. Zauważcie, jak uniwersalna jest ta funkcja i ile informacji można z niej uzyskać. Oczywiście to
tylko przykład i kto chce może napisać swoją
własną na dowolny procesor. Moja napisana
jest dla procesora ’51 z kwarcem 11,059MHz.
Przerobienie jej na inny typ (np. AVR) sprowadza się do zmiany realizacji opóźnienia
(Delay) zależnie od konkretnego typu i zegara. Opóźnienie to powinno być kilkanaście...kilkadziesiąt razy krótsze od czasu trwania krótkiego impulsu, który dla wartości elementów jak na schemacie jest rzędu
500µs (podkreślam – rzędu). Oprócz tego należy wtedy dobrać liczby określające długość
określające minimalną długość impulsu długiego i za długiego (u mnie są to 40 i 80).
·
Rys. 2 Przebiegi wyjściowe
M
A
L
K
E
Schemat montażowy przedstawiony został
na rysunku 3. Montaż jest typowy i nie wymaga komentarza. Zaczynamy od zworek
a kończymy na tranzystorach i układach
scalonych (warto zastosować podstawki).
Miejsca do podłączenia przycisków oznaczono ich numerami, pod jakimi będą dekodowane w programie. Po zmontowaniu ze sprawnych elementów układ od razu działa poprawnie. Do jego sprawdzenia przyda się jakikolwiek analizator stanów logicznych. W moim
przypadku był to najzwyklejszy tranzystor
NPN podłączony do portu drukarkowego
A
Montaż i uruchomienie
R
stanu wysokiego lub niskiego. Nie chodzi
jednak o połowę czasu, gdyż przebieg wytwarzany przez prościutki generator na U2A wcale nie ma wypełnienia 50%, ale to nic nie
przeszkadza. Tak więc 1 okres ma 2 impulsy,
1,5 okresu to 3 impulsy itd.. Załóżmy przykładowo, że wciśnięto przycisk S3 oznaczony
numerem 2. Pierwsze narastające zbocze
przebiegu generatora U2A spowoduje pojawienie się stanu wysokiego na Q1 U2 oraz
natychmiastowe wystąpienie na wyjściu stanu niskiego. Po wygenerowaniu 2 impulsów
stan wysoki przejdzie na wyjście Q2, po 4 impulsach pojawi się na Q3. Po wytworzeniu
piątego impulsu układ zacznie generować
szósty, ale po jego zakończeniu stan wysoki
pojawi się na wyjściu Q4, do którego dołączony jest zwarty przycisk S3. Spowoduje to
natychmiastowe wyzerowanie U1 i zamknięcie bramki U2C. Na wyjściu układu pojawi
się stan wysoki (zatkany T1) na czas trwania
1 okresu, czyli kolejnych 2 impulsów. Ponieważ podczas generowania impulsu numer 6
(jak i każdego parzystego) na wyjściu również był stan wysoki, to w rezultacie po wystąpieniu 5 impulsów pojawi się tam długi
stan wysoki o czasie trwania 3 kolejnych impulsów (szósty impuls zleje się z dwoma następnymi). Dalsze trzymanie S3 znów spowoduje wystąpienie 5 krótkich impulsów i jednego długiego itd. Puszczenie przycisku natychmiast resetuje U1 i po chwili wyłącza generator. Jeśli ktoś, zamiast S3, wciśnie np. S4
(numer 3), to układ wytworzy przebieg,
w którym pomiędzy dwoma impulsami długimi będzie 7 krótkich (o 1 okres więcej – to
oczywiste), z których każdy trwa ok. 3 razy
krócej niż długi. Dla przycisku numer 1 będą
to 3 krótkie impulsy, a dla numer 0 – tylko 1.
Mam nadzieję, że dostrzegacie już ogólną zależność: po wciśnięciu przycisku numer
N (0...7) układ generuje przebieg,
w którym pomiędzy dwoma długimi impulsami jest 2N+1 krótkich. Pomocą będzie
rysunek 2, na którym przedstawiłem przebiegi na wyjściu układu po wciśnięciu kilku wybranych przycisków na tle przebiegu z nóżki
3 U2. Strzałki pokazują momenty, w których
resetowany jest U1. Przebiegi takie są łatwe
do zdekodowania przez mikroprocesor – aby
otrzymać numer przycisku, wystarczy policzyć, ile krótkich impulsów występuje pomiędzy dwoma długimi, odjąć 1 i podzielić
przez 2. Ze względu na to, że w układzie występuje prościutki generator z jedną bramką,
dobrze jest do dekodowania brać nie pierwszą, ale drugą lub trzecią serię impulsów –
w pierwszej mogą występować impulsy
o mniej jednolitych czasach niż w kolejnych
seriach. Warto też sprawdzić, czy po długim
impulsie kończącym analizowaną serię występuje kolejny krótki impuls, rozpoczynający serię następną. Zapobiegnie to błędom występującym podczas ekstremalnie krótkich
naciśnięć przycisków, kiedy to mogłoby dojść
51
i darmowy programik ściągnięty z sieci.
Przebiegi na wyjściu powinny być takie jak
na rysunku 2. Oprócz programu z listingu 1
na stronie EdW (w dziale FTP) znajdziecie
prosty program (źródło i *.bin), który wyświetla numer wciśniętego przycisku na wyświetlaczu LCD (interfejs HD44780). Może
on służyć do przetestowania układu. Jednak ze
względu na duży rozrzut progów przełączania
bramek w różnych egzemplarzach kostek 4093
może się zdarzyć, że choć układ będzie wytwarzał przebiegi o prawidłowym kształcie oraz
wartości elementów będą takie jak na rysunku
1, to czasy impulsów będą się bardzo różniły od
tych w modelu. Na wyświetlaczu będzie się
wtedy notorycznie pojawiał napis Error!!!! lub
jakieś „głupoty”. Sporadyczne pojawianie się
tego napisu nie świadczy o błędzie w układzie,
lecz o wystąpieniu przekłamań, które w rzeczywistym świecie się zdarzają. Chodzi o to, aby
właściwie na nie zareagować i nie uznać błędnej transmisji za właściwą. Najprościej jest ją
po prostu zignorować. Jeżeli jednak napis ten
pojawia się często, to należy zmierzyć czasy
analizatorem i zmienić liczby 40 i 80 w funkcji
Wait_for_long na odpowiednie. Jeśli zaś chodzi
o samą stabilność tego generatora, to choć
jest ona słaba, tutaj w zupełności wystarczy.
Listing 1. Funkcja dekodująca
Rys. 3 Schemat montażowy
// Przykład wykorzystania tej funkcji
main()
{
_data unsigned char numer,err;
#include <regat8x2051.sfr>
#define in
P3_2
unsigned char Wait_for_long(unsigned char* num)
{
_bit last;
_data unsigned char licznik,stan,i;
*num=0;
stan=0;
licznik=0;
in=1;
last=in;
while(1)
{
i=1;
while(i--);
licznik++;
if(licznik>40)
stan=1;
if(licznik>80)
return 1;
in=1;
if(in!=last)
{
if(stan)
else
{
}
}
while(1)
{
}
}
// DELAY
// zły długi
return 0;
// dobry długi
last=in;
licznik=0;
(*num)++;
in=1;
while(in);
while(!in);
// czeka na poczatek
// ignorujemy pierwszy impuls
err=Wait_for_long(&numer);
err=Wait_for_long(&numer);
// ignorujemy ten numer
// ważny numer
// wykorzystanie zmiennej numer
// + prosta ochrona przed błędami
if(!err && numer<16)
{
numer--;
numer>>=1;
Wykaz elementów
Rezystory
R1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .100kΩ
R2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .220kΩ
R3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22kΩ
R4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .470kΩ
R5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1MΩ
R6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10kΩ
Kondensatory:
C1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10nF MKT
C2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .220nF MKT
C3 . . . . . . . . . . . . . . . . . . . . . . . . . . . .100nF ceramiczny
Półprzewodniki:
U1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4017
U2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4093
T1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .BC548B
T2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .BC558B
Inne:
S1-S8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Przyciski zwierne, typ zależny od konkretnego zastosowania
(nie wchodzą w skład kitu AVT).
Komplet podzespołów z płytką
jest dostępny w sieci handlowej AVT
jako kit szkolny AVT-22673
52
}
else
{
}
}
}
// -1
// numer=numer/2
// .... tu wykorzystujemy zmienną numer
// reakcja na błąd
// czeka na puszczenie przycisku
while(!Wait_for_long(&numer));
Częstotliwość musiałaby się rozjechać dwukrotnie, żeby wystąpiły błędy, a do tego w typowych warunkach pracy nie dojdzie. Jest ona
natomiast mocno zależna od napięcia zasilania – wspomniane liczby trzeba dobrać przy
takim napięciu, przy jakim układ ma pracować docelowo. Ostatecznie można napisać
ulepszoną, bardziej uniwersalną funkcję, która
nie będzie miała tych liczb wpisanych „na
sztywno”. Będzie mierzyć krótkie impulsy
i czekać na wystąpienie długiego impulsu
o nie ściśle określonym czasie, ale rzeczywi-
ście ponad 2-krotnie dłuższego od krótkich.
Uniezależni to nas od rozrzutów i innych niestabilności – wszystko w rękach programistów. Wszystkie stałe czasowe można dobrać
wedle uznania. Gotowy moduł wstawiamy do
urządzenia z mikrokontrolerem, gdzie brakuje
nam wyprowadzeń i problem mamy z głowy.
Interesująco wygląda możliwość dołączenia
do naszej klawiaturki generatora (np. 36kHz)
i budowa prostego pilota IRED.
Arkadiusz Antoniak
[email protected]
E l e k t ro n i k a d l a Ws z y s t k i c h