ISIX w przykładach w języku C. Obsługa klawiatury matrycowej
Wtorek, 01 Marzec 2011
W ostatnim przykładzie wprowadzającym w programowanie
ISIX-a, w języku C pokażemy w jaki sposób obsłużyć klawiaturę
matrycową. Klawiatury tego typu dzięki multipleksowaniu
pozwalają na obsługę wielu klawiszy przy stosunkowo niewielu
wymaganych liniach I/O. W klasycznych rozwiązaniach bez systemu
mikroprocesorowego, obsługa klawiatury matrycowej najczęściej jest
realizowana przez procedurę obsługi układu czasowo-licznikowego.
70 ELEKTRONIKA PRAKTYCZNA 3/2011
NOTATNIK KONSTRUKTORA
Dodatkowe materiały
na CD i FTP
W przypadku systemu operacyjne-
go, procedurę obsługi klawiatury nume-
rycznej możemy delegować do specjalnie
w tym celu utworzonego wątku. W bieżą-
cym przykładzie do linii GPIO dołączymy
telefoniczną klawiaturę matrycową 4×4
oraz znany z wcześniejszych przykładów
wyświetlacz z telefonu N3310. Wątek ob-
ISIX w przykładach
w języku C
Obsługa klawiatury
matrycowej
W ostatnim przykładzie wprowadzającym w programowanie
ISIX-a, w języku C pokażemy w jaki sposób obsłużyć klawiaturę
matrycową. Klawiatury tego typu dzięki multipleksowaniu
pozwalają na obsługę wielu klawiszy przy stosunkowo niewielu
wymaganych liniach I/O. W klasycznych rozwiązaniach bez systemu
mikroprocesorowego, obsługa klawiatury matrycowej najczęściej jest
realizowana przez procedurę obsługi układu czasowo-licznikowego.
sługi klawiatury w momencie wykrycia
wciśnięcia klawisza będzie wysyłał wia-
domość zawierającą kod klawisza, która
będzie odczytywana i wyświetlana na
ekranie N3310 przez wątek wyświetla-
nia. Do realizacji powyższego przykładu
konieczne będzie dołączenia modułu KA-
modLCD1 oraz modułu klawiatury matry-
cowej KAmodKB4×4 (obydwa produkcji
KAMAMI).
Opis działania programu
Zasadę działania programu z uwzględ-
nieniem podziału na wątki przedstawiono
na rysunku 1.
Wykonywanie aplikacji rozpoczyna
się od funkcji main() - listing 1. Na po-
czątku tworzony jest niezależny wątek
obsługi LED D1, a następnie kolejka FIFO
składająca się z 10 kodów klawiszy. Jeżeli
proces tworzenia kolejki został wykonany
pomyślnie, to jest tworzony wątek obsługi
klawiatury oraz wątek wyświetlania. Na-
stępnie jest uruchamiany planista zadań
systemu ISIX. Za obsługę klawiatury od-
powiada wątek kbd_task (listing 2).
Na początku wykonywana jest proce-
dura inicjalizująca klawiaturę (listing 3),
która wykonuje konfigurowanie linii ko-
lumn PE0..PE3 w kierunku wejścia, nato-
miast linii wierszy PE4..PE7 w kierunku
wyjścia.
Funkcja konfigurowania portów jest re-
alizowana przez procedurę io_config_ext,
która umożliwia skonfigurowanie grupy
pinów w wybranym porcie, przekazanych
przez maskę bitową.
Po wykonaniu czynności początko-
wych wątek przechodzi do pętli nieskoń-
czonej, gdzie następuje cykliczna zmiana
stanów wyjść ROW, a następnie odczyt
bitów linii COL. Na postawie znajomości
aktualnie aktywowanego stanu na liniach
List. 2. Wątek obsługi klawiatury
ISIX_TASK_FUNC(kbd_task,entry_params)
{
//Initialize gpio port keyscan
keyscan_init();
//Fifo pointer
fifo_t *key_fifo = (fifo_t*)entry_params;
//Main loop
for(;;)
for(int row=KEYSCAN_FIRST_ROW;row<=KEYSCAN_LAST_ROW ;row<<=1)
{
//Set row output
io_set_clr_mask( KEYSCAN_PORT, row, KEYSCAN_ROW_PINS );
//Wait one tick before read
isix_wait(1);
int col = io_get_mask( KEYSCAN_PORT, KEYSCAN_COL_PINS);
if(col>0)
{
//If col selected translate key and sent to disp
key_t key = key_translate( row, col );
isix_fifo_write( key_fifo, &key, isix_ms2tick(KEY_SCAN_INTERVAL));
}
//Wait one ms
isix_wait_ms(KEY_SCAN_INTERVAL);
}
}
Listing 1. Funkcja main() programu obsługi klawiatury matrycowej
int main(void)
{
//Create ISIX blinking task
isix_task_create( blinking_task, NULL,ISIX_PORT_SCHED_MIN_STACK_DEPTH, TASK_
PRIO_LED);
//Create fifo msgs
fifo_t *key_fifo = isix_fifo_create( 10, sizeof(key_t) );
if(key_fifo)
{
//Create isix tasks (key and disp)
isix_task_create(kbd_task,key_fifo,TASK_STK_SIZE,TASK_PRIO_KEY);
isix_task_create(display_srv_task,key_fifo,TASK_STK_SIZE,TASK_PRIO_DISP);
}
isix_start_scheduler();
//Start the sheduler
}
Rysunek 1.
71ELEKTRONIKA PRAKTYCZNA 3/2011
ISIX w przykładach w języku C
Listing 5. Wątek odczytujący stan klawiszy
static ISIX_TASK_FUNC(display_srv_task, entry_params)
{
fifo_t *temp_fifo = (fifo_t*)entry_params;
key_t key;
nlcd_init(); //Initialize LCD
//Put welcome string
nlcd_put_string( ?www.boff.pl?, 0, 0 );
nlcd_put_string( ?Clicked key:?, 0, 1 );
for(;;)
{
//Read data from fifo
if(isix_fifo_read( temp_fifo, &key, ISIX_TIME_INFINITE )==ISIX_EOK)
{
nlcd_set_position(6,2);
nlcd_put_char(key);
}
}
}
Listing 4. Funkcja zwracająca kod wciśniętego klawisza
static inline char key_translate(int row, int col)
{
switch(row) /* Select row */
{
case KEYSCAN_ROW1_BIT:
switch(col) /* Select col */
{
case KEYSCAN_COL1_BIT: return ?1?;
case KEYSCAN_COL2_BIT: return ?2?;
case KEYSCAN_COL3_BIT: return ?3?;
case KEYSCAN_COL4_BIT: return ?A?;
}
break;
case KEYSCAN_ROW2_BIT:
switch(col) /* Select col */
{
case KEYSCAN_COL1_BIT: return ?4?;
case KEYSCAN_COL2_BIT: return ?5?;
case KEYSCAN_COL3_BIT: return ?6?;
case KEYSCAN_COL4_BIT: return ?B?;
}
break;
case KEYSCAN_ROW3_BIT:
switch(col) /* Select col */
{
case KEYSCAN_COL1_BIT: return ?7?;
case KEYSCAN_COL2_BIT: return ?8?;
case KEYSCAN_COL3_BIT: return ?9?;
case KEYSCAN_COL4_BIT: return ?C?;
}
break;
case KEYSCAN_ROW4_BIT:
switch(col) /* Select col */
{
case KEYSCAN_COL1_BIT: return ?*?;
case KEYSCAN_COL2_BIT: return ?0?;
case KEYSCAN_COL3_BIT: return ?#?;
case KEYSCAN_COL4_BIT: return ?D?;
}
break;
}
return ?x?; //Unknown key
}
Listing 3. Inicjalizowanie linii I/O do obsługi klawiatury
//Initialize the port configuration
static void keyscan_init(void)
{
RCC->APB2ENR |= RCC_APB2Periph_GPIOE;
//Input push pull +GND
io_config_ext( KEYSCAN_PORT, KEYSCAN_COL_PINS, GPIO_MODE_INPUT, GPIO_CNF_IN_
PULLUP );
io_clr_mask(KEYSCAN_PORT, KEYSCAN_COL_PINS);
//Output row to zero
io_config_ext( KEYSCAN_PORT, KEYSCAN_ROW_PINS, GPIO_MODE_10MHZ, GPIO_CNF_
GPIO_PP );
io_clr_mask(KEYSCAN_PORT, KEYSCAN_ROW_PINS);
}
ROW (wierszy), oraz badania stanu linii
wejściowych kolumn COL (kolumn), mo-
żemy ustalić kod wciśniętego klawisza.
Po ustawieniu linii wierszy odczyt linii
kolumn następuje z opóźnieniem jednego
cyklu systemu operacyjnego (1 ms), tak
aby dać czas na ustalenie się sygnałów
wyjściowych. W przypadku wykrycia sta-
nu wysokiego na jakiejkolwiek linii COL
wywoływana jest funkcja key_translate(),
która na podstawie aktualnego wiersza
i aktualnej kolumny
zwraca kod wciśniętego
klawisza (listing 4).
Działanie funkcji
tłumaczącej jest bardzo
proste i sprowadza się
do zwrócenia odpowied-
niego kodu klawisza na
podstawie aktualnego
wiersza oraz aktualnej
kolumny wykorzystując
podwójną konstrukcję
switch-case.
Tak przekształcony
kod klawisza jest na-
stępnie wysyłany do
kolejki FIFO, po czym
jest wywoływana funk-
cja isix_wait_ms(), która
usypia wątek odczytu
klawiatury na 9 ms. Za
odczytywanie stanu kla-
wiszy odpowiada wątek
display_srv_task (listing
5). Działanie wątku roz-
poczyna się od inicjali-
zacji biblioteki obsługi
wyświetlacza NCD3310,
wyświetlenia w liniach
0-1 komunikatu powitalnego, a następnie
przejścia do pętli głównej wątku. W pętli
za pomocą funkcji isix_fifo_read(), odczy-
tywana jest kolejka FIFO znaków. Jeżeli
w kolejce znajduje się jakiś znak, kod od-
czytanego znaku wyświetlany jest na wy-
świetlaczu LCD. Jeżeli w kolejce nie ma
żadnego znaku, wówczas wątek jest usy-
piany.
Lucjan Bryndza
Zobacz więcej w kategorii Notatnik konstruktora