Professional Documents
Culture Documents
Wielopoziomowe Menu W C
Wielopoziomowe Menu W C
Wielopoziomowe Menu W C
Wielopoziomowe menu w C
Opisane w†artykule funkcje wykona- Jednym z†najwiÍkszych ìpoøeraczyî czasu i†energii
³em jako demonstracjÍ sposobu imple-
mentacji menu. Nie s¹ one zwi¹zane programisty, obok uruchomienia programu, jest tak zwany
z†øadnym konkretnym urz¹dzeniem. Do
interfejs uøytkownika. Mikrokontroler nie potrzebuje do pracy
ich uruchomienia uøy³em p³ytki ekspe-
rymentalnej w³asnej konstrukcji, zbliøo- wyúwietlacza, klawiatury, diod úwiec¹cych LED i†temu
nej funkcjonalnie do AVR Starter Kit
i†zawieraj¹cej mikrokontroler AT89S8252,
podobnych elementÛw, o†ile nie jest to úciúle zwi¹zane
programator oraz z³¹cza doprowadzaj¹ce z†operacjami zapisu lub odczytu danych. Wszystkie te
sygna³ do wyprowadzeÒ mikrokontrole-
ra. Do p³ytki pod³¹czy³em wyúwietlacz drobiazgi s¹ potrzebne nam, ludziom, abyúmy mogli
LCD (pracuje z†interfejsem 4-bitowym) wprowadzaÊ parametry i†poznaÊ rezultat wykonania przez
oraz klawiaturÍ wykonan¹ jako matrycÍ
3†wierszy i†4†kolumn (w sumie 12 kla- mikrokontroler okreúlonego programu.
wiszy). Port P2, do ktÛrego pod³¹czy- W†artykule przedstawiÍ sposoby tworzenia jedno-
³em klawiaturÍ, dodatkowo wyposaøy³em
w†rezystory pull-up o†wartoúci 47 kΩ. i†dwupoziomowych menu, wyúwietlanych na typowym
Uøy³em ich ze wzglÍdu na d³ugie kable
wyúwietlaczu LCD 4†linie po 20 znakÛw.
³¹cz¹ce klawiaturÍ z†portem mikrokont-
rolera. W†tab. 1 i†na rys. 1 zawarto
opis po³¹czeÒ elektrycznych. numer 0†argumentu (argument wywo³a- ki) poleceniem curr &= Row_mask (ilo-
nia np. 0xFE), drugiej bitu numer czyn bitowy). WartoúÊ maski rÛwnieø
Odczyt klawiatury 1†itd. W†pliku nag³Ûwkowym KBD3X4.H zdefiniowana zosta³a w†pliku nag³Ûwko-
Funkcje odczytuj¹ce klawiaturÍ za- za pomoc¹ dyrektywy #define zdefinio- wym. Bit aktywny przyjmuje stan niski.
deklarowa³em jako zewnÍtrzne funkcje wano w³aúciwe wartoúci argumentu wy- W†zwi¹zku z†tym, øe ³atwiej jest porÛw-
biblioteczne i†umieúci³em w†module wo³ania funkcji KBD_Read (Co- nywaÊ bity znajduj¹ce siÍ w†stanie wy-
o†nazwie KBD3X4. Pierwsza z†nich char lumn_1...3), ktÛre pÛüniej uøywane s¹ sokim, wartoúÊ zwracanej zmiennej jest
KBD_Read(char column) s³uøy†do obs³u- przez funkcjÍ Key_Number. negowana (polecenie return(~curr), ì~î
gi klawiatury na poziomie sprzÍtu, ope- SposÛb funkcjonowania KBD_Read to operator dope³nienia jedynkowego).
ruj¹c na portach mikrokontrolera. Dru- jest nastÍpuj¹cy: argument column jest Funkcja Key_Number przyporz¹dko-
ga - char Key_Number(void) - przydzie- zapisywany do portu klawiatury i†tym wuje kombinacjom bitÛw odczytanych
la klawiszom odpowiednie kody. samym linia ktÛrejú z†kolumn przyjmu- z†portu mikrokontrolera okreúlone kody.
Funkcja KBD_Read w†wyniku dzia- je stan niski. Na skutek przyciúniÍcia Konstrukcja programu zbliøona jest do
³ania zwraca unikatow¹ dla kaødego (zwarcia) klawisza linia wiersza - bÍ- budowy klawiatury. Warunki if tworz¹
z†wciúniÍtych klawiszy, odpowiadaj¹c¹ d¹ca normalnie w†stanie wysokim - rodzaj matrycy, na ktÛrej przeciÍciach
mu wartoúÊ lub 0†- jeúli øaden z†kla- przejdzie w†wymuszony stan niski. Stan znajduj¹ siÍ kody klawiszy. Wartoúci
wiszy nie jest wciúniÍty. Nie pracuje ten jest dwukrotnie odczytywany przez Row_1...4 rÛwnieø predefiniowane s¹
ona poprawnie, jeúli wciúniÍto wiÍcej mikrokontroler: za drugim razem po 50 w†pliku nag³Ûwkowym. Jedynka na po-
niø jeden klawisz. Zawsze zwracana milisekundach. Zrobi³em tak, aby zycji bitu wiersza odpowiada wciúniÍ-
jest jako pierwsza kombinacja klawiszy upewniÊ siÍ, øe klawisz zosta³ naciú- ciu klawisza. W†przypadku, gdy øaden
z†kolumny bÍd¹cej pierwsz¹ odczytan¹. niÍty celowo i†by³o to zamiarem uøyt- z†klawiszy nie jest naciúniÍty, funkcja
Jako argument wywo³ania spodziewane kownika. Jest to rÛwnieø bardzo prosty zwraca wartoúÊ 0.
jest wyzerowanie bitu odpowiadaj¹cego filtr zak³ÛceÒ mog¹cych pojawiÊ siÍ na
odczytywanej kolumnie. W†zwi¹zku doprowadzeniu portu. Menu jednopoziomowe
z†tym, øe kolumna pierwsza klawiatury Aby zapobiec wp³ywowi na wynik Najprostszym rodzajem menu jest me-
pod³¹czona jest do P2.0, druga do P2.1 dzia³ania funkcji bitÛw innych niø przy- nu jednopoziomowe. Charakteryzuje siÍ
a†trzecia do P2.2, odczytowi pierwszej porz¹dkowane wierszom klawiatury, s¹ ono tym, øe po wybraniu opcji nastÍpu-
kolumny odpowiada wyzerowanie bitu one maskowane (ustawiane w†stan nis- je bezpoúrednie wywo³anie akcji. Menu
takie jest ³atwe do wykonania, jeúli
Tab. 1. Przypisanie funkcji wyprowadzeniom mikrokontrolera w†ca³oúci mieúci siÍ na ekranie LCD.
Nazwa portu Oznaczenie Funkcja Znacznie gorzej jest, gdy ma ono na
przyk³ad 8†pozycji, a†na ekranie mamy
P2.0 PC0 Doprowadzenie pierwszej kolumny matrycy klawiszy do dyspozycji 2†czy 4†linie. WÛwczas
P2.1 PC1 Doprowadzenie drugiej kolumny matrycy klawiszy musimy nie tylko okreúliÊ nazwy po-
P2.2 PC2 Doprowadzenie trzeciej kolumny matrycy klawiszy szczegÛlnych opcji, ale rÛwnieø sposÛb
P2.3 PC3 Doprowadzenie drugiego wiersza matrycy klawiszy wyúwietlania menu po przekroczeniu roz-
miaru ekranu. Wyliczenie tych wszyst-
P2.4 PC4 Doprowadzenie trzeciego wiersza matrycy klawiszy
kich zmiennych zajmuje duøo pamiÍci
P2.5 PC5 Doprowadzenie czwartego wiersza matrycy klawiszy programu oraz czasu mikrokontrolera.
P2.6 PC6 Doprowadzenie pierwszego wiersza matrycy klawiszy Pocz¹tek programu (czÍúÊ deklara-
P3.4 PD4 Sygna³ RS wywietlacza LCD cyjna zmiennych) zawiera definicjÍ ty-
P3.5 PD5 Sygna³ READ wywietlacza LCD pu o†nazwie menuitem. Jest to struktu-
ra pojedynczego rekordu opisuj¹cego li-
P3.6 PD6 Sygna³ ENABLE wywietlacza LCD
niÍ menu. Rekordy te s¹ nastÍpnie
P1.4 PB4 Bit 5 szyny danych wywietlacza LCD zgrupowane w†tabeli menus, tam teø
P1.5 PB5 Bit 6 szyny danych wywietlacza LCD nadawana jest im wartoúÊ. Kilku s³Ûw
P1.6 PB6 Bit 7 szyny danych wywietlacza LCD omÛwienia wymaga rola poszczegÛlnych
P1.7 PB7 Bit 8 szyny danych wywietlacza LCD pÛl rekordu.
w†pamiÍci mikrokontrolera. Sytuacja menu i†jego opcje. WrÛÊmy do sposobu Ogranicza ona od gÛry wartoúÊ zmien-
wygl¹da zupe³nie inaczej, gdy tworzo- tworzenia definicji menu g³Ûwnego. Na nej globalnej POS_IN_SUBMENU, ktÛra
na jest aplikacja dla komputera PC list. 1 przedstawiono schemat budowy nie moøe byÊ wiÍksza niø maxsubopt-1
niø†gdy dla mikrokontrolera. Ten pier- definicji menu g³Ûwnego oraz odpowia- i†jest sprawdzana po kaødym naciúniÍciu
wszy w†porÛwnaniu z†drugim posiada daj¹cych mu opcji podmenu. klawisza w†gÛrÍ czy w†dÛ³.
niewyobraøalne wrÍcz zasoby do wyko- Tablica mainmenu zawiera wykaz Po wejúciu do podmenu zaczyna
rzystania, istne ìmorze pamiÍciî, przy definicji etykiet i†parametrÛw menu rÛwnieø dzia³aÊ klawisz o†kodzie 0x0B
dodatkowo bardzo duøej szybkoúci dzia- g³Ûwnego. Polu wskaünikowemu o†na- pe³ni¹cy rolÍ podobn¹ do ESCAPE
³ania. Pewnych nawykÛw†i†przyzwycza- zwie nextmenu nadawana jest wartoúÊ w†komputerze PC. Jego naciúniÍcie powo-
jeÒ (o ile takie s¹) nie da siÍ po pros- adresu - wskazania do wykazu opcji duje, øe nastÍpuje powrÛt do menu
tu w†tym momencie wykorzystaÊ, cho- podmenu, jeúli takie istnieje. Kolorami g³Ûwnego bez podejmowania jakiejkolwiek
ciaø nowe, pojawiaj¹ce siÍ na rynku wyrÛøniono te przypisania. W†takim akcji i†moøna wÛwczas dokonaÊ innego
mikrokontrolery imponuj¹ wrÍcz swoi- przypadku pole retval ma wartoúÊ 0. wyboru. WybÛr zawsze potwierdzany jest
mi zasobami sprzÍtowymi. Zostawmy Gdy podmenu nie istnieje (moøe to byÊ przez naciúniÍcie klawisza ENTER.
jednak rozwaøania i†wrÛÊmy do opisu na przyk³ad opcja ìUruchomî, ìObliczî Podobnie jak w†poprzednim przyk³a-
sposobu wykonania menu. itp.), polu retval nadawana jest war- dzie, program g³Ûwny zawiera inicjaliza-
Przy jego budowie pos³uøy³em siÍ toúÊ, ktÛr¹ ma zwrÛciÊ funkcja, a†polu cjÍ wyúwietlacza, wywo³anie funkcji ob-
rozwi¹zaniami z†pierwszego przyk³adu nextmenu naleøy†przypisaÊ wartoúÊ 0. s³ugi menu oraz konstrukcjÍ switch -
programowania, jednak wyraünie zosta- Wymagane jest, aby kaøda tablica- case w†celu rozpoznania wybranej opcji.
³y rozgraniczone menu g³Ûwne od me- wykaz etykiet podmenu by³a zakoÒczo-
nu podrzÍdnego. Rozgraniczaj¹ je za- ny rekordem, w†ktÛrym co najmniej po- Uwagi na temat programu
rÛwno funkcje realizuj¹ce wyúwietlanie le name ma wartoúÊ 0. Rekord ten jest Funkcje w†moich przyk³adach czÍsto
etykiet i†wybÛr spomiÍdzy nich, jak niezbÍdny, poniewaø na podstawie jego pos³uguj¹ siÍ wskaünikami do struktur.
i†typy rekordÛw uøytych do deklaracji. po³oøenia obliczana jest przez funkcjÍ Ich konstrukcja oraz sposÛb zapisu jest
Rozpocznijmy analizÍ od menu g³Ûwne- wyúwietlaj¹c¹ podmenu d³ugoúÊ wyka- specyficzny i†wymaga kilku s³Ûw omÛ-
go. Dla potrzeb budowy tablicy-wykazu zu opcji, a†tym samym liczba etykiet wienia zw³aszcza dla tych osÛb, ktÛre
opcji menu g³Ûwnego zadeklarowa³em do wyúwietlenia. spotykaj¹ siÍ z†nimi po raz pierwszy.
typ o†nazwie menuitem. Zawiera on Menu g³Ûwne wyúwietlane jest Definicja tabeli zawieraj¹cej rekordy
pola poznane juø wczeúniej (name, ptr w†identyczny sposÛb jak to by³o robio- jest doskona³ym mechanizmem zw³asz-
i†y0) i†oprÛcz nich nowe, o†nazwach ne w†przypadku menu jednopoziomowe- cza przy tworzeniu baz danych i†pli-
nextmenu oraz retval. go. Jego obs³ug¹ zajmuje siÍ funkcja kÛw dyskowych. I†chociaø w†tych przy-
Pole nextmenu to wskaünik do ob- Main_Menu i†jej funkcje us³ugowe. Jako k³adach programÛw nie s¹ uøywane
szaru wykazu opcji odpowiadaj¹cego rezultat zwraca ona liczbÍ jednobajto- øadne zbiory znajduj¹ce siÍ na dysku,
mu podmenu. W†przypadku, gdy na- w¹ bÍd¹c¹ kodem wybranej opcji. to jednak tablica rekordÛw do z³udze-
stÍpny poziom nie jest dostÍpny, Po naciúniÍciu klawisza o†kodzie nia przypomina strukturÍ bazy danych,
wskaünikowi nadawana jest wartoúÊ 0. 0x0C umownie funkcjonuj¹cego jako EN- a†leø¹cy gdzieú w†obszarze code pamiÍ-
Z†tym polem úciúle zwi¹zana jest za- TER, funkcja sprawdza, czy pole next- ci mikrokontrolera wykaz - plik dysko-
wartoúÊ pola retval. Zawiera ono licz- menu przyporz¹dkowane bieø¹cej pozy- wy. Istniej¹ dwie podstawowe metody
bÍ zwracan¹ przez funkcjÍ w†przypad- cji zawiera jak¹ú wartoúÊ. Jeúli tak, fun- odwo³ywania siÍ do pozycji w†takiej
ku wyboru opcji. Jak ³atwo siÍ domyú- kcja wywo³uje obs³ugÍ podmenu jako strukturze:
liÊ, wartoúÊ wpisana do retval nie ma parametr, podaj¹c zawartoúÊ odpowied- - z†zastosowaniem indeksÛw (np. me-
øadnego znaczenia w†przypadku, gdy niego pola nextmenu. W†zwi¹zku z†tym, nus[1], menus[5] itd.),
wywo³ywane jest podmenu. WÛwczas øe chcia³em napisaÊ funkcjÍ uniwersal- - z†zastosowaniem wskaünika (wskaüni-
to, funkcja obs³ugi menu zwrÛci war- n¹, zdoln¹ do wyúwietlenia podmenu kÛw).
toúÊ zapisan¹ w†polu retval w³aúciw¹ o†rÛønych iloúciach etykiet, przy wywo- Ta pierwsza metoda jest bardzo
dla danej opcji (etykiety) podmenu. ³aniu funkcja musi obliczyÊ, jaka jest prosta. Ilustruje j¹ przyk³ad umieszczo-
Wskaünik nextmenu jest typu sub- liczba pozycji wykazu przekazanego ja- ny na list. 2. Indeks to po prostu nu-
menuitem. Ten typ zmiennych zosta³ ko argument wywo³ania. Minimalna mer pozycji w†tabeli, do ktÛrego ø¹da
utworzony dla potrzeb tablic-wyka- wartoúÊ to 1, maksymalna 127. Koniec dostÍpu aplikacja. Jeúli mamy do czy-
zÛw†opcji menu drugiego poziomu. Jest wykazu rozpoznawany jest po tym, øe nienia z†tabel¹ zawieraj¹c¹ 10 elemen-
on prawie taki sam, jak uøywany do pole name (etykieta menu) ma wartoúÊ tÛw, to indeks moøe przyj¹Ê wartoúci
potrzeb menu g³Ûwnego. ale oprÛcz pod- znaku o†kodzie 0. Wynik obliczeÒ zapa- od 0†do 9. Gdy mamy do czynienia
stawowych pÛl (etykieta name, po³oøe- miÍtywany jest w†zmiennej maxsubopt. z†tablic¹ struktur, dostÍp do pola moø-
nie znaku wyboru y0, offset wskaünika
ptr oraz wartoúci zwracanej przez menu
List. 2. Odwołanie do tablicy rekordów poprzez indeksy
retval) nie zawiera øadnych wskaünikÛw
typedef struct //definicja typu - struktury (rekordu) danych
do nastÍpnych wykazÛw opcji. {
£atwo jest rozbudowaÊ podmenu char x; //struktura zawiera 3 pola typu char: x, y, colour
o†nastÍpne poziomy. Wystarczy uøyÊ po- char y;
dobnych mechanizmÛw jak dla budowy char colour;
} attr;
poziomu 2. Jest w†tym jednak drobna
trudnoúÊ: naleøy w†jakiú sposÛb podaÊ data attr points[10]; //deklaracja tablicy zawierającej rekordy danych
uøytkownikowi informacjÍ, z†ktÛrego me-
void main()
nu wybierana jest opcja, ot chociaøby {
przez wyúwietlenie úcieøki - opisu miej- char temp;
sca, w†ktÛrym siÍ znajduje. Trudno jest attr pt;
znaleüÊ to miejsce na ekranie LCD
points[0].x = 1; //nadanie wartości polu x tablicy wskazywanemu
o†niewielkich rozmiarach. W†praktyce //przez indeks 0
ograniczam wiÍc menu budowanych temp = points[8].y; //pobranie wartości pola y wskazywanemu przez indeks 8
przez siebie urz¹dzeÒ co najwyøej do //do zmiennej temp
pt = point[2]; //przepisanie rekordu danych z tablicy (indeks=2)
2...3 poziomÛw i†zazwyczaj nie ma po-
//do zmiennej pt będącej
trzeby tworzenia dalszej hierarchii. Za- } //tego samego typu, co element tablicy
miast tego warto jest przemyúleÊ uk³ad
List. 3. Odwołanie do tablicy rekordów poprzez wskaźnik Odwo³anie do pola struktury umoø-
liwia operator wygl¹daj¹cy jak strza³ka
typedef struct //definicja typu - struktury (rekordu) danych
{ skierowana w†prawo, utworzony ze
char x; //struktura zawiera 3 pola typu char: x, y, colour znaku wiÍkszoúci oraz odejmowania (-
char y; >) nastÍpuj¹cego bezpoúrednio po nim.
char colour; Stosuj¹c go, naleøy†pamiÍtaÊ, øe ma
} attr;
bardzo wysoki priorytet. Operacje
data attr points[10]; //deklaracja tablicy zawierającej rekordy danych (pointer+temp)->x oraz temp+pointer->x
data attr *pointer = &points; //deklaracja wskaźnika oraz nadanie mu wartości nie s¹ rÛwnowaøne. Jednak bardziej
//początkowej: wskazania na początek tablicy points
jaskrawy przyk³ad stanowi porÛwnanie
void main() sposobu funkcjonowania wyraøeÒ
{ ++pointer->x oraz (++pointer)->x.
char temp; W†tym pierwszym przypadku wyraøe-
attr pt;
nie zwiÍksza zmienn¹ x o†1, a†nie
pointer->x = 1; //nadanie wartości polu x tablicy wskazywanemu wskaünik do struktury. W†drugim
//przez indeks 0 wskaünik jest zwiÍkszany przed odwo-
temp = (pointer+8)->y; //pobranie wartości pola y wskazywanemu przez
//indeks 8 do zmiennej temp
³aniem do struktury i†na skutek tego
pt = pointer+2; //przepisanie rekordu danych z tablicy (indeks=2) nastÍpuje przejúcie do nastÍpnego
//do zmiennej pt będącej w†kolejnoúci elementu tablicy.
} //tego samego typu, co element tablicy Na tej samej zasadzie wyraøenie:
- *pointer->x udostÍpnia coú, na co
wskazuje x,
na uzyskaÊ podaj¹c po kropce jego na- pointer_1++; //spowoduje przesunię- - *pointer->x++ zwiÍksza x†po udostÍp-
zwÍ: zmienna = menu[1].ptr. //cie wskazania zmiennej nieniu obiektu wskazywanego przez
Inaczej ma siÍ sytuacja, gdy odwo- //points[0].x na points[0].y x,
³anie do struktury odbywa siÍ przez //(o 1 bajt) - (*pointer->x)++ zwiÍksza coú, na co
wskaünik. Pos³uømy siÍ tym samym pointer_2++; //spowoduje przesunię- wskazuje x,
przyk³adem - na list. 3 umieszczono //cie wskaźnika z rekordu - *pointer++->x zwiÍksza zmienn¹
program zmodyfikowany w†taki sposÛb, //points[0] na points[1] i jest pointer po udostÍpnieniu obiektu
aby odwo³ania do pÛl nastÍpowa³y //równoważne wyrażeniu wskazywanego przez x.
przez wskaünik a†nie przez indeks. //pointer_1 = Jak wspomnia³em wczeúniej, wyko-
Wskaünik powinien byÊ tego same- //pointer_1 + sizezeof(attr) rzystuj¹c mechanizmy uøyte do budowy
go typu, co wskazywany obszar da- pointer_1 += 8; //spowoduje przesu- drugiego poziomu menu ³atwo jest do-
nych. W†konsekwencji wszelkie opera- //nięcie wskaźnika o 8 bajtów, to daÊ nastÍpne poziomy. Wystarczy, øe
cje arytmetyczne na nim wykonywane //jest na zmienną points[2].y typ submenuitem bÍdzie zawiera³†wskaü-
powoduj¹ jego zmianÍ o†tak¹ liczbÍ baj- pointer_2 += 8; //spowoduje przesu- nik do nastÍpnego wykazu menu, a†fun-
tÛw, jaki jest rozmiar wskazywanego //nięcie wskaźnika o 8 rekordów, kcja Sub_Menu zapamiÍta i†przechowa
elementu. Ilustracj¹ tej zasady jest po- //to jest na pozycję 9 w tabeli stan zmiennej POS_IN_SUBMENU. Praw-
niøszy przyk³ad: pointer_1 += temp; //spowoduje dopodobnie bÍdzie rÛwnieø wymagaÊ
//przesunięcie wskazania o 2 baj- s³owa kluczowego reentrant (kompilator
data char *pointer_1 = &points; //ty, to jest na zmienną RC-51) powoduj¹cego, øe funkcja moøe
data attr *pointer_2 = &points; //points[0].colour byÊ wywo³ywana rekurencyjnie. Rozbu-
data char temp = 2; pointer_2 += temp; //spowoduje dowÍ pozostawiam jednak inwencji
... //przesunięcie wskaźnika o 2 re- w³asnej Czytelnika.
... //kordy, to jest na pozycję Jacek Bogusz, AVT
... //3 w tabeli jacek.bogusz@ep.com.pl