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