No generalnie ma to być bardzo proste menu które będzie miało do wyboru 4 podprogramy.
Kod:
#include <MenuBackend.h> // dołączenie biblioteki
#include <LiquidCrystal_I2C.h>// --- definiujemy dla LCD własne znaki strzałek: dół, lewo, prawo, gora-dół i powrót ---
uint8_t arrowUpDown[8] = {0x4,0xe,0x15,0x4,0x15,0xe,0x4};
uint8_t arrowDown[8] = {0x4,0x4,0x4,04,0x15,0xe,0x4};
uint8_t arrowRight[8] = {0x0,0x4,0x2,0x1f,0x2,0x4,0x0};
uint8_t arrowLeft[8] = {0x0,0x4,0x8,0x1f,0x8,0x4,0x0};
uint8_t arrowBack[8] = {0x1,0x1,0x5,0x9,0x1f,0x8,0x4};
LiquidCrystal_I2C lcd(0x3F,16,2); // definicja pinów dla LCD (sprawdź piny w swoim LCD)
volatile int zm =-1; // to dla kontroli zmiany stanu klawiatury
volatile int x=-1; // zmienna pomocnicza
volatile int stan_Analog; // wartość na wejściu Analogowym dla klawiaturki analogowej
char *linia1; // pierwsza linia wyświetlanego tekstu na LCD
char *linia2; // druga linia wyświetlanego tekstu na LCD
// --- tworzymy wszystkie opcje Menu: ---------------------------------------
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent); // konstruktor
MenuItem P1 = MenuItem(" PLIK",1);
MenuItem P11 = MenuItem(" Nowy",2);
MenuItem P12 = MenuItem(" Otworz",2);
MenuItem P13 = MenuItem(" Szkicownik",2);
MenuItem P14 = MenuItem(" Przyklady",2);
MenuItem P15 = MenuItem(" Zapisz",2);
MenuItem P16 = MenuItem(" Zapisz jako..",2);
MenuItem P17 = MenuItem(" Zaladuj",2);
MenuItem P18 = MenuItem(" Exit",2);
MenuItem P2 = MenuItem(" EDYCJA",1);
MenuItem P21 = MenuItem(" Wytnij",2);
MenuItem P22 = MenuItem(" Kopiuj",2);
MenuItem P23 = MenuItem(" Wklej",2);
MenuItem P24 = MenuItem(" Zaznacz",2);
MenuItem P25 = MenuItem(" Znajdz",2);
/* --- Teraz pozycjonujemy menu ( zgodnie z ustawieniem podanym powyżej) ------------
add - dodaje w pionie, addRight - dodaje w poziomie z prawej , addLeft dodaje z lewej
*/
void menuSetup() // funkcja klasy MenuBackend
{
menu.getRoot().add(P1); // ustawiamy korzeń Menu, czyli pierwszą opcję
P1.add(P11); // rodzic PLIK ma dziecko Nowy więc dodaje je w pionie
P11.add(P12);P11.addLeft(P1); // poniżej Nowy jest Otworz więc także w pionie
// a addLeft(P1) pozwoli nam wrócić klawiszem w lewo do PLIK
P12.add(P13);P12.addLeft(P1); // analogicznie robimy ze wszystkimi podopcjami dla PLIK
P13.add(P14);P13.addLeft(P1);
P14.add(P15);P14.addLeft(P1);
P15.add(P16);P15.addLeft(P1);
P16.add(P17);P16.addLeft(P1);
P17.add(P18);P17.addLeft(P1);
P18.addLeft(P1);P18.add(P11); // tutaj zamykamy pętlę i wracamy do pierwszej podopcji
// dzieki temu nie musimy wracać na górę przez uciążliwe
// klikanie klawisza Up
P1.addRight(P2); // po prawej dla PLIK jest EDYCJA
P2.add(P21); // rodzic EDYCJA ma dziecko Wytnij
P21.add(P22);P21.addLeft(P2); // poniżej Wytnij jest Kopiuj
P22.add(P23);P22.addLeft(P2); // analogicznie dla wszystkich podopcji
P23.add(P24);P23.addLeft(P2);
P24.add(P25);P24.addLeft(P2);
P25.addLeft(P2);P25.add(P21); // i zamknięcie pętli oraz ew. powrót do pierwszej opcji
}
// ----------- uff... nareszcie :-) -----------------------------------------------------------------------
void menuUseEvent(MenuUseEvent used) // funkcja klasy MenuBackend - reakcja na wciśnięcie OK
// tutaj właśnie oddajemy menu na rzecz akcji obsługi klawisza OK
{
// przykładowa reakcja na wcisnięcie klawisza OK w opcji Otworz :
if (used.item.getName() == " Otworz") // Uwaga - dokładnie taki sam ciąg " Otworz" jak w menu !!!
// bo przecież getName() pobiera nazwę
{
lcd.setCursor(1,0);lcd.print("Otwieram drzwi"); // info
digitalWrite(0,HIGH);delay(2000);digitalWrite(0,LOW); // na 2 sekundy pin 0 otrzymał stan wysoki
// czyli np. otworzyły się drzwi
lcd.setCursor(1,0);lcd.print(" ");lcd.setCursor(1,0);lcd.print(linia1); //poprzedni stan LCD
}
// --- Reakcja na wciśnięcie klawisza -----------------------------------------------------------------
void menuChangeEvent(MenuChangeEvent changed); // funkcja klasy MenuBackend
{
/* tak naprawdę to tylko tutaj przydaje się ów shortkey i służy przede wszystkim do wzbogacenia menu
o symbole strzałek w zależności co wybrano. Wszystko co tutaj się wyprawia jest pokazywane na LCD.
*/
int c=changed.to.getShortkey(); // pobieramy shortkey (1,2,3, lub4)
lcd.clear(); // bez komentarza
lcd.setCursor(0,0);
if(c==1) // jeśli to menu głowne (shortkey=1) to:
{
lcd.write(3); // strzałka w lewo
strcpy(linia1,changed.to.getName()); // tworzymy napis w pierwszej linii
lcd.print(linia1); // wyświetlamy ją
lcd.setCursor(15,0);lcd.write(4); // strzałka w prawo
lcd.setCursor(0,1);lcd.write(5); // strzałka w dół
lcd.setCursor(15,1);lcd.write(5); // strzałka w dół
}
if(c==2) // jeśli to podmenu dla dziecka - (shortkey=2) to:
{
lcd.print("*"); // rysujemy gwiazdkę
strcpy(linia2,changed.to.getName()); // tworzymy napis w pierwszej linii
lcd.print(linia1); // wyświetlamy ją
lcd.setCursor(15,0);lcd.print("*"); // gwiazdka
lcd.setCursor(0,1);lcd.write(6); // druga linia i strzałka powrotu (arrowBack)
lcd.print(changed.to.getName()); // wyświetlamy nazwe "dziecka"
lcd.setCursor(15,1);lcd.write(7); // strzałka góra-dół
}
if(c==3) // jeśli dziecko ma dziecko - (shortkey =3) to:
{
lcd.print("*"); // gwiazdka
strcpy(linia2,changed.to.getName()); // kopiujemy akt. nazwe opcji menu do zmiennej linia2
lcd.print(linia1); // i wyświetlamy pierwszą linię
lcd.setCursor(15,0);lcd.print("*"); // gwiazdka
lcd.setCursor(0,1);lcd.write(6); // druga linia i strzałka arrowBack
lcd.print(changed.to.getName()); // wyświetlamy wnuka w drugiej linii
lcd.setCursor(15,1);lcd.write(4); // strzałka w prawo bo są wnuki
}
if(c==4) // jeśli to wnuk (shortkey =4) to:
{
lcd.print("*"); // gwaizdka
lcd.print(linia2); // w pierwszej linii wyświetlamy dziecko ( czyli rodzica wnuka)
lcd.setCursor(15,0);lcd.print("*"); // gwaizdka
lcd.setCursor(0,1);lcd.write(6); // druga linia i strzałka arrowBack
lcd.print(changed.to.getName()); // wyświetlamy wnuka
lcd.setCursor(15,1);lcd.write(7); // strzałka góra-dół
}
{
pinMode(8,INPUT);digitalWrite(8,HIGH);
pinMode(9,INPUT);digitalWrite(9,HIGH);
pinMode(10,INPUT);digitalWrite(10,HIGH);
pinMode(11,INPUT);digitalWrite(11,HIGH);
pinMode(12,INPUT);digitalWrite(12,HIGH);
if(digitalRead(8)==LOW) return 1;
if(digitalRead(9)==LOW) return 3;
if(digitalRead(10)==LOW) return 4;
if(digitalRead(11)==LOW) return 0;
if(digitalRead(12)==LOW) return 2;
return -1;
}
}
// ============================================================================================
//
void setup()
{
linia1=new char[16]; // zainicjowanie dynamicznego wskaźnika do tekstu
linia2=new char[16]; // to BARDZO WAŻNE, bo wskażnik dynamiczny musi wskazywać na
// z góry określone miejsce w pamieci. Gdybyśmy tego nie zrobili
// to wcześniej czy później programik mógłby wskoczyć w nieokreślony
// bliżej obszar pamięci, co może skutkować nieodwracalnymi konsekwencjami
// łącznie z przestawieniem Fuse Bitów !!!
// Proszę uważać na wszystkie dynamiczne wskaźniki, TAKA DOBRA RADA :-)
Serial.begin(9600); // inicjacja Seriala, głównie do testów
lcd.begin(16, 2); // inicjacja LCD
lcd.createChar(3,arrowLeft); // tworzymy w pamięci LCD 5 własnych znaków dla strzałek
lcd.createChar(4,arrowRight);
lcd.createChar(5,arrowDown);
lcd.createChar(6,arrowBack);
lcd.createChar(7,arrowUpDown);
pinMode(8,INPUT);digitalWrite(8,HIGH); // tu przykładowe piny cyfrowe dla 3 wersji funkcji czytaj_3(1,2,3,11,12)
pinMode(9,INPUT);digitalWrite(9,HIGH);
pinMode(10,INPUT);digitalWrite(10,HIGH);
pinMode(11,INPUT);digitalWrite(11,HIGH);
pinMode(12,INPUT);digitalWrite(12,HIGH);
menuSetup(); // funkcja klasy MenuBackend - tu tak naprawdę tworzymy nasze menu
menu.moveDown(); // idziemy do pierwszej opcji - PLIK, moveDown bo pierwotnie byliśmy w root
// to tak jak w Awatarze drzewa rosną korzeniami do góry :-)
}
// --- I nadszedł czas na neverending story :-) --------------------------------------------
void loop()
{
x=czytaj_3(0);delay(30); // odczytujemy stan klawiatury:
/*
Ja używam funkcji czytaj_1() bo mam akurat klawiaturkę podpiętą pod A0
Jeśli masz inna klawiaturkę to użyj funkcji czytaj_2 lub czytaj_3 - patrz opis
Ponadto musisz pamietać że w funkcji obsługo klawisza OK - menuUseEvent(MenuUseEvent used)
także musisz użyć odpowiedniej wersji funkcji czytaj !!!
*/
if(zm!=x) // jesli była zmiana stanu to :
{
switch(x) // sprawdzamy co nacisnieto
{
case 0: menu.moveRight();break; // jesli naciśnięto klawisz w Prawo to przesuń menu w prawo
case 1: menu.moveUp();break; // menu do góry
case 2: menu.moveDown();break; // menu w dół
case 3: menu.moveLeft();break; // menu w lewo
case 4: menu.use();break; // wciśnięto OK więc skok do funkcji menuUseEvent(MenuUseEvend used)
// to w tej funkcji właśnie obsługujemy nasze Menu, tu sprawdzamy
// jaką opcję wybrano i tutaj tworzymy kod do obslugi zdarzenia.
}
} zm=x; // przypisanie zmiennej zm wartości x po to, aby dluższe wciskanie tego
// samego klawisza nie powodowało ponownej generacji zdarzenia.
// program reaguje na zmianę stanu klawiatury.
}
// === KONIEC ===========================================================