Na temat obsługi klawiszy było już sporo. Mirek już świetnie opisał swoją funkcję SuperDebounce na blogu, dlaczego więc zakładam temat ? Swoją naukę prowadzę trochę swoim torem (książkę już raz przeczytałem od dechy do dechy i zabieram się za utrwalanie czyli czytanie drugi raz
)
Zazwyczaj nowa wiedza najlepiej mi wchodzi jeśli znam zagadnienie od podszewki. Miałem ostatnio wolną chwilę i zacząłem przerabiać moje proste podstawowe bascomowe programy (których używam na co dzień) na C w ramach poznania i utrwalenia jego składni z uwzględnieniem wszystkich dobrodziejstw jakie C udostępnia. Na pierwszy ogień poszedł właśnie program obsługi wielofunkcyjnego klawisza krótki/długi, który zaprojektowałem dawno temu w bascomie. Temat jak sądzę zawsze aktualny
Chciałem się podzielić moim rozwiązaniem z kilku powodów:
1. Ze względu na jego nieco odmienną konstrukcję niż większość tu prezentowanych, naprawdę niewielki rozmiar samej funkcji, ogromną elastyczność i prostotę w rozbudowie o dodatkowe funkcje (np. 5 funkcji pod jednym klawiszem);
2. Program nie blokuje pętli głównej.
3. Być może jeszcze coś z tej funkcji się wyciśnie jakimiś innymi poleceniami, itp. i bardziej ją udoskonali co przełoży się zapewne na dalsze poszerzenie mojej wiedzy
Co potrzebne? Potrzebny jest jeden timer programowy w przerwaniu wywoływanym co 10ms (to jednostka podziału jaką używam w przeliczeniach funkcji) oraz jedna zmienna dla każdego klawisza.
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Najpierw fragment programu, który można umieścić liniowo czyli ciurkiem w pętli głównej - w końcu jeśli badamy 1-2 przyciski to można sobie czasem na to pozwolić. Zaczniemy od podstawowej funkcji czyli:
krótki wcisk - wykonuje się jeden raz pierwsza funkcja (po puszczeniu przycisku)
długi wcisk - wykonuje się jeden raz druga funkcja
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
To wszystko...
No prawie wszystko, na początku trzeba tylko zdeklarować odpowiednie zmienne:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Jak widać program jest tak prosty, że chyba każdy początkujący powinien bez najmniejszych problemów przeanalizować jego działanie i natychmiast zrozumieć ideę
Wspomnę tylko, że jeśli. np. przerwania ustawione są na 1000Hz - 1ms (a nie 100Hz - 10ms jak w przykładzie) to odświeżanie licznika tk trzeba wpisać 10. Analogicznie dla innych częstotliwości wywoływania przerwania.
Przykładowe ustawienie przerwań dla Atmega8 może wyglądać tak:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Oczywiście należy pamiętać też o odpowiednim ustawieniu kierunków portów dla przycisków, ale to chyba oczywiste. W przypadku użycia kolejnego klawisza należy zadeklarować kolejną zmienną, np. Lk2 i teoretycznie nowy licznik programowy tk... W praktyce licznik ten wystarczy przenieść (wspomnę o tym dalej) tuż przed sprawdzaniem wciśniętego klawisza (lub klawiszy) i po prostu omijać cały fragment jeśli tk będzie różne od 0. Strata czasowa będzie pomijalna - dodatkowy jeden "If" nie zatrzyma przecież pętli głównej na długo.
Kolejna odsłona procedury to:
krótki wcisk - wykonuje się jeden raz pierwsza funkcja (po puszczeniu przycisku)
długi wcisk - wykonuje się cyklicznie (repeat) druga funkcja
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Jak widać wiele się nie zmieniło. Dodałem tylko jeden warunek przy badaniu długiego wcisku i cofanie licznika o potrzebny czas "repeat"
I jeszcze jedna funkcja (i wcale nie ostatnia
) :
krótki wcisk - wykonuje się jeden raz funkcja (od razu)
długi wcisk - wykonuje się powtarzanie funkcjijęzyk c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Jak widać zmiany nieco większe, ale chyba też komentarza nie wymagają
W każdym przypadku debounce ustawione na co najmniej 20-30ms. Czas ten spokojnie można uznać za bezpieczny, a jeśli komuś nie pasuje może go zwiększyć.
No dobrze, skoro już udało mi się bascomowe wersje przerobić na C to teraz zgodnie z zasadami jak mawia Mirek (i tu trzeba go słuchać) spróbowałem na podstawie jego przycisku przerobić powyższe na działającą funkcję.
I tu wielki ukłon w stronę Mirka (+dobre piwo), bo dzięki temu poznałem przekazywanie parametrów adresu portu i ogólnie zabawa ze wskaźnikami co na tak prostym przykładzie napisanym samodzielnie naprawdę pozwoliło mi to szybko zrozumieć.
Poniższy program to zbiór gotowych funkcji razem z prostą demonstracją działania dwóch przycisków. Można tu nawet 10 przycisków dać, a program nadal nie będzie blokował pętli (o ile wywoływane funkcje pod klawiszami tego nie uczynią) nawet jeśli jednocześnie będą wciśnięte wszystkie(!) klawisze. Celowo użyłem przynajmniej dwóch wywołań ze względu na timer, o którym wcześniej wspominałem i o zasadzie przeskoczenia wywoływania tychże funkcji, ale trzeba go też w ten sposób zastosować nawet dla jednego przycisku (choć wtedy lepiej użyć gotowej wstawki z pierwszej części posta). Jest to w sumie chyba jedyna wada, z którą nie mogę się na razie uporać. tzn. można by ale niepotrzebnie rozbudowało by to program, a w takiej wersji też działa wystarczająco dobrze i myślę, że to wyrzucenie timera przed sekcję guzików nie jest jakimś kłopotem. A może ktoś ma jakiś pomysł jak to załatwić w jednej linijce ?
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Jak widać kod jest banalny i ewentualne zmiany można sobie wprowadzać w zależności od potrzeb. Funkcjonalność rozbiłem na trzy procedury z prostej przyczyny - zazwyczaj wiadomo co klawisz będzie robił i czy będzie potrzebny repeat czy nie wtedy stosujemy tylko to co nam potrzeba.
Składni nie będę tu opisywał, bo idealnie ją widać w programie demonstracyjnym. Miłego klawiszowania