obsługa przycisków w AVR

Potrzebuję ogólnej porady jak zrobić coś takiego:

  1. główny program robi coś tam w pętli, która trwa około 0,1s

  1. przycisk generuje przerwanie INT0, obsługa przerwania jest bardzo krótka (np. tylko zapalenie/zgaszenie LED-a)

  2. dłuższe naciskanie przycisku nie powoduje kolejnego przerwania, dopiero następne przyciśnięcie

Mam problem z punktem 3. Na wyjściu procedury obsługi INT0 blokuję przerwania, ale w "głównej pętli" muszę je odblokować, i w tym momencie znowu pojawia się przerwanie, jeśli przycisk jest cały czas wciśnięty. Czy jest jakiś "standardowy" sposób obsługi czegoś takiego, może jakiś przykładowy programik (w asemblerze)?

I druga sprawa, związana z przyciskami:

- jak wykrywać długie naciśnięcie przycisku (np. pół sekundy, chcę coś włączać/wyłączać poprzez dłuższe naciśnięcie guzika, żeby nie włączało się przypadkowo w kieszeni)

- jak wykrywać "podwójne kliknięcie"?

Paweł

Reply to
Paweł Paroń
Loading thread data ...

Zapomniałem dodać, że chodzi o tiny15L, problemem może być trzypoziomowy stos.

Paweł

Reply to
Paweł Paroń

Paweł Paroń napisal(a):

Ja tam w ogole nie robie obslugi klawiatury w przerwaniach.... Raczej jest to bardziej klopotliwe rozwiazanie. Czemu chcesz tak zrobic?

Probowales chociaz rozpisac algorytm? To jest proste.

Reply to
Marcin E. Hamerla

Np. żebym mógł włączyć układ, gdy jest w stanie "sleep". No i żeby czas reakcji na przycisk był jak najkrótszy, w programie będą jeszcze pętle "sekundowe", przynajmniej taki mam na razie pomysł. Jak inaczej zrobić, żeby przycisk zawsze zadziałał, niezależnie od tego w którym miejscu jest wykonywany program (poza obsługą innego przerwania)?

Gdybym miał rozpisany algorytm, to bym nie pytał jak to się robi. Chodzi mi właśnie o ten dobry algorytm, bo mam zero doświadczenia i prawdopodobnie nie zrobię tego porządnie za pierwszym razem, na pewno są jakieś sprawdzone sposoby.

Paweł

Reply to
Paweł Paroń

Jest nota aplikacyjna Atmela, gdzie _oprocz_ wejscia przyciski sa podpiete pod INTcos. Warto IMHO zajrzec.

Zesmy na ten temat dyskutowali jakies 2 miesiace temu baardzo obficie - scieraly sie rozne szkoly, zady i walety (albo jakos tak ;-)) roznych metod byly walkowane do bolu. Wiec

formatting link
jest zalecane. Ja robie obsluge przycisku w glownej petli, czekam, az juzer pusci przycisk i potem wykonuje akcje.

Pozdrawiam

Marcin Stanisz

Reply to
Marcin Stanisz

Witam.

Tak jak napisal Marcin E. Hamerla, obsluga klawiatury poza przerwaniem. Powinienes sprawdzac nie tylko moment wcisniecia przycisku, ale tez moment jego puszczenia. Dopiero taka para (wcisniecie - wycisniecie) powoduje wykonanie jakiejsc tam funkcji.

się

Do tych dwoch punktow (dlugie nacisniecie i podwojne klikniecie) bedziesz potrzebowal jakiegos licznika czasu (tu sie moze przydac przerwanie, tyle ze z timera). I tak:

  1. dlugie nacisniecie - mierzysz odstepy miedzy wcisnieciem a wycisnieciem przycisku;
  2. podwojne klikniecie - mierzysz czas miedzy wycisnieciem a wcisnieciem.

Tak to najogolniej moze wygladac.

Reply to
l.0l0

Marcin Stanisz napisal(a):

U mnie zalezy to od aplikacji. Ale generalnie wiaze procedure odczytu klawiszy z przerwaniem zegarowym. Wtedy problem debouncingu sam sie rozwiazuje. No i oczywiscie bez problemu robi sie double-click.

Reply to
Marcin E. Hamerla

Ja to robie przy uzyciu przerwan zegarowych,

Z reguly poswiecam 1 timer na cos co symuluje zegar i wywoluje je np 50 x na sekunde, uzywam to przerwanie do obslugi wyswietlacza (jezeli akurat mam LED) itp. oraz odczytu klawiatury.

Z reguly wyglada to tak, ze mam 1 rejestr nazwany bufor klawiatury, + dodatkowe informacje ile cykli zegarowych jest potrzebych do nastepnej kontroli, znacznik klawisza w buforze i licznik Autorepeat

klawiature sprawdzam ok 5 - 10 x na sekunde (czyli np. co dziesiate przerwanie). Jezeli to co jest na porcie rozni sie od wartosci w buforze i to oznacza to wcisniecie klawisza (lub puszczenie) i wtedy przepisuje port do bufora oraz ustawiam znacznik ze wcisnieto klawisz, oraz rejestr opoznienia autorepeat (np 10 odczytow - tj ok 1 sek). Jezeli wartosc na porcie jest taka sama jak w buforze klawiatury i ewidentnie jest jakis klawisz ciagle wcisniety to zmniejszam licznik AutoRepeat Gdy licznik Autorepeat osiagnie wartosc 0 to ustawiam go na nowo i znowu markuje, ze wcisnieto klawisz - wartosc w buforze klawiatury jest niezmieniona.

Tyle przerwanie.

Dodatkowo mam procedure odczytu klawiatury, ktora sprawdza czy znacznik wcisniecia jest ustawiony odczytuje wartosc z bufora i kasuje znacznik.

Jest to dosc przymitywne, ale dziala skutecznie, problem drgan zestykow praktycznie nie istnieje gdyz kontrole nad klawiatura ma zegar a nie dedykowane przerwanie.

Casami uzywam przerwania zewnetrznego tylko po to aby obudzic procesor. wtedy klawisze sa polaczone przez diody do pinu obslugujacego przerwanie zewnetrzne

Pozdrawiam Tomasz Kolecki

Reply to
tomaszkolecki

A jak wtedy rozpoznajesz długie przyciśnięcie, albo "dwuklik"? Czy robisz jakiś pomiar czasu wewnątrz obsługi tego przerwania, czy może obsługa tego przerwania jest zawsze krótka, a w kolejnych wywołaniach sprawdzasz czy przycisk jest nadal wciśnięty (albo czy jest wciśnięty drugi raz w krótkim czasie).

Masz może jakiś przykładowy programik, który to obsługuje?

Paweł

Reply to
Paweł Paroń

Paweł Paroń napisal(a):

Trzeba czas zliczac. Inaczej sie nie da.

W obrebie przerwania jest oczywiscie licznik. Procedura obslugi klawiatury musi zapamietywac czasy oraz stany i natej podstawie dokonywac zwrotu kodu operacji (X, Long X, double click X), do petli glownej.

Tak, jest krotka. Patrz jak wyzej.

Te rozubodowane procedury mam w assemblerze 8051. Dawno z nich nie korzystalem. Moge potem poszukac, ale nei teraz, bo zaraz z dzieckiem ide do lekarza.

Reply to
Marcin E. Hamerla

On Behalf Of Paweł Paroń

Ale wygodny. Taki przykładowy nie istniej. Zawsze wymaga przeróbki, która z kolei wymaga pewnej wiedzy i umiejętności samodzielnego myślenia. Ale naprowadzę. Tabela stanu klawiszy. Tabela zwłoki dla danego klawisza. W przerwaniu od timera - jeśli w tabeli zwłoki danego klawisza wartość jest większa od 0 wtedy dekrementujemy. Badając stan klawisza i jego czas zwłoki można określić:

  1. jak długo jest wciśnięty
  2. czy nastąpił dwuklik.
  3. załatwiamy sprawę debouncing.
  4. możemy sparametryzować czas naciśnięcia. To akurat mało przydatne przy klawiszach, ale jak się robi coś gdzie automatyka jest pomieszana z manual'em to się przydaje. ;-)

pzdr Artur PS No i zapomniałem o tabeli old_klawisz, żeby było z czym porównywać.

PS2 Własnie się drinkuję, wiec jeśli coś niejasno piszę, to proszę o wybaczenie. ;-)

Reply to
ziel

Szczęśliwie się złożyło, że umiejętność samodzielnego myślenia posiadam, a wiedzę nabywam dość szybko. Przykładowe programy jak najbardziej istnieją, chociażby noty aplikacyjne producenta, nie chodziło mi o program gotowy, tylko właśnie o przykładowy.

Dzięki, tak to mniej więcej wczoraj zrobiłem i nawet działa :)

Paweł

Reply to
Paweł Paroń

Paweł Paroń napisal(a):

Przerwanie zegarowe pozwoli Ci na to samo.

Ale przeciez nie musi i nie moze byc zbyt krotki. Nie musi, bo przeciez czas wcisniecia nie jest zbyt krotki. Nie moze ze wzgledu na debouncing.

Zdecydowanie przerwanie zegarowe. BTW zauwaz, ze jesli bede petle sekundowe, to mozesz gubic zdarzenia. Obsluge bardziej skomplikowanej klawiatury dobrze jest rozbic na dwie czesci. Jedna czesc siedzi na przyklad w przerwaniu, skanuje porty, sprawdza czasy, itd i na tej podstawie generuje kody przycisku. Obrobka zdarzen powinna byc w petli glownej.

Reply to
Marcin E. Hamerla

Właśnie dlatego mój pierwszy pomysł był taki, żeby klawisz generował przerwanie, ale już wiem, że to nie jest najlepszy sposób.

Tak właśnie robię. Klawiatura nie jest przesadnie skomplikowana, ma jeden przycisk. Wczoraj napisałem procedurkę, która rozróżnia krótkie i długie przyciśnięcie oraz "dwuklik", mam też pomysł na "trójklik".

Paweł

Reply to
Paweł Paroń

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.