1. Nie tworzymy komunikatu o kodzie 0 - ten kod został zarezerwowany do oznaczenia braku danych w kolejce.
Kody takich samych zdarzeń dla różnych przycisków dobrano tak, że leżą one obok siebie - ułatwi to ich obsługę.
Funkcje obsługujące klawiaturę umieścimy w module system. Potrzebują one zdefiniowania jednej stałej, utworzenia jednej zmiennej oraz jednej struktury, co pokazuje listing 116.
DłakJŻdsgo klawisza:
Listing 114 deklaracja funkcji kolejki w systenuh
vo1d sy£temjrsgCleax(void)J uir.t8_t system_msgPut(uint8_t msg); uir.tB L system_msq3et (void); uint8 t sys.em_msgWai r.For(void);
Idea rozwiązania Obsługa klawiatury w przerwaniach z wykorzystaniem kolejki komunikatów
Poznawane do tej pory propozycje funkcji obsługi klawiatury miały tę wspólna cechę, że funkcja zwracająca stan przycisków dokonywała jednocześnie jego badania. Proponuję tera/ spojrzeć na sprawę zupełnie inaczej - badajmy stan przycisków oraz dokonujmy w okresowo wywoływanej funkcji obsługującej przerwania. Same funkcje zwracające stan przycisków będą sięgać do zmiennych wewnętrznych oznacza to, że znacznie szybciej zwrócą wynik.
Ponadto podczas sprawdzania przycisku od razu wyślemy odpowiedni komunikat.eśli zdarzy się interesujące nas zdarzenie.
Hołd 1 Licznik crosu trzymania klawteu
PnyofcknacttntytyHJi Ho*d<W*X-1 (MAX-1 -odUfeank <*rj* rtyfcńw)
Raptu 1 łucznik do następnego powtórzenia
Zmienna przechowują aktualną prędkość repatpc}
0-brak '•petycji
Obrazek w ramce pokazuje potrzebne nam zmienne oraz wyjaśnia ich działanie. Zauważ sposób wykorzystania zmiennej pola Hołd do jednoczesnego odkłoconia drgań styków oraz do wykrycia długiego trzymania klawisza.
Listing 115- komunikaty przycisków
// Naciśnięcie przycisku #define tdm_swup 1 #Hefine idm_SWDOWN 2 // Przycisk przytrzymany #define idh_SWUP_hold 3 #de*ine idm_swdown_hold 4 // Powtórzenie przycisku Pcefine idm_swup_repeat 5 #definp tdm_swdown_repeat 6 // Przycisk został puszczony // 2anim nastąpiło przytrzymanie frdefine IDM_SWUP_5HORT 7 #defi ne idm_swuown_SHORT 8
Od razu, na podstawie opisu zmiennych w ramce powyżej muże-my napisać dwie pomocnicze funkcje zwracające informację o aktualnym stanie klawiatury - listing 117. Pojawia się tutaj nieutworzony jeszcze przez nas typ danej: KBDJKEY. Jest to typ wyliczeniowy przyporządkowujący symbolicznym nazwom klawiszy udpowiednie indeksy. Umieszczamy go w pliku system.h, przed deklaracją dwóch stworzonych funkcji - listing 118.
Listing 119-funkcja ustawiająca prędkość repetycji // zmaca poprzednia wartość
uint8 t sysiem_kbd3etRepeatSpeed(uintR t rep) {
uint£_t rep_last ■ syste/n_kbdRepeótSpeed,' c:i();
aystem_KbdRepeatSpeeci « rep; system_kbd[0].RepeatCnt * rep; sys:.em_kbd[l] .RepeatCnt = rep; sei();
return rep_iast;
l.Uting 116
- zmienne wykorzystywane przez obsługę klawiatury
// jednostka - 40ms fdetire KBD_H0LDTIME 25 (...
static uint8_t oystem_kbclRepećŁSpeed ■ 0; static struct: 3YSTem_kbd_key status 1
uir.t8_t HoldTime; uir.t8_t RepeatCnt;
} system_kbd[2] ®
{ (KB3__HOLDTIRE, 0),
(KBD_HOLDTIME, 0}};
Listing 117 - fuakcje podające aktualny stan klawiszy
1nl1ne Uint8_t sys::em_kbdT.sPressec(KBD KEY key)
return (syst©m_kfcd[kcy] .IIoldTime < KBD_HOLDTIME i);
inłine uints t system kbdZsHeld(KBD_KEY key)
return (systenr_kbd[key] .HoldTin-e = 0);
Listing 118 - deklaracja funkcji z listingu 117 oraz wprowadzenie zmiennej typu KBD KEY
typedef enum kbd_key
KRD_UE»KB3_S W1, KBD_DDWN-KBD SW2,
}kbd_key;
inłine uint8_t system_kbdIsPressed(KBD_KEY key) inłine uint8_t system kbdIsHeldCKBC_KEf key);
Listing 120 - skanowanie jednego klawisza
// key - indeks zmiennej opisującej stan przycisku
// mask - maska, zawierająca 1 tylko tam gdzie znajduje sic przycisk
static void <bd_ProcessKeyCuint8_t key, uintEt masie)
struct SYSTEM :<BD_KEY_STATUS* pStat ■ system_kbd+key;
1fCpin(sw_port) & mask)
// Jeśli właśnie puszczony, test C7y nie oyło krótk ego // trzymania:
if (pStat->HoldTimę I- KRH HOLDT3ME && pStat->:toldTir.f I- ')) system_msgPutClON_SWUP__SHORT -t- key);
Przycisk puszczony pStat->HoldTime - KBD_HOLDTIMEJ pStat->RepeatCnt — system_kbdRepeat5peed;
>
else
// Przycisk naciśnięty // Jeśli drugi raz - przyc’s< odkłócony: ifCpStat->HoldTirre — KBD HOLDTIME-1) system_msgPut(IDM SWUP + key); właśnie mi ja czas trzymania: else 1f(pStat->HoldTime c= 1)
system msqPut(iDM SWLP RSPEAT + key);
.=5y.9t em_msgPut (i DM_SWUP_HOLD + key);
1
if(pS-at->HoldTime 1* 0)
-CpSLaL->HoldTime)J ełse ifCsyst9iT_kPclRepeatSpeed !■ 0)
// Mamy do czynienia z trzymaniem, badamy repetycję:
{
ifCpSta-->F.epeatCnt 0)
iyste»_msgPut(lDM_swu?_REPEAr + koy);
pStat->RepeatCnt ■ systcn_kbdRepeaLSpeed;
else
-(pStat->RepeatCnt);
42 Sierpień 2006 Elektronika dla Wszystkich