Krawi92 Napisano Grudzień 26, 2021 Udostępnij Napisano Grudzień 26, 2021 Witam, chciałbym aby ktoś podpowiedział, jak podchodzić do tworzenia prostego menu w oparciu o wyswietlanie na lcd. Dziś w sumie udało mi się na lcd wyswietlać czas i datę w oparciu o PCF8583, ale chciałem zrobić opcje, aby użytkownik mógł go sobie samemu ustawić. W oparciu o 4 microswitche to zrobiłem i instrukcje switch: while(1){ if (!keylock1 && !(PIND & (1<<KEY1))){ keylock1=1; licznik++; if (licznik > 3)licznik=0; }else if (keylock1 && (PIND & (1<<KEY1)))keylock1++; switch(licznik){ case 0:RTC_Event(); break; case 1:display_menu2(&czas); // tu wyświetla sie opcja ustaw date break; case 2:display_menu(); // tu wyswietla sie opcja ustaw czas break; case 3:zapisano_czas(); // tu zapisujemy do rtc dane ze struktury i komunikujemy uzytkownika ze zostala wszystko zapisane break; } } W ten prostacki sposób do tego podszedłem. Chciałbym jednak postarać się zrozumieć, jak rozbudowywuje się jakieś większe menu, gdzie ustawień może być więcej. Że za pomoca przycisków chodzimy po menu, wracamy do głównego itp. Czy jest to gdzieś jakos fajnie opisane od postaw? @_LM_ aktualnie prowadzi wpis, w którym tworzy taką bibliotekę, ale jestem jeszcze zbyt początkujący, żeby coś z tego zrozumieć 😄 Cytuj Link do komentarza Share on other sites More sharing options...
_LM_ Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 13 minut temu, Krawi92 napisał: @_LM_ aktualnie prowadzi wpis, w którym tworzy taką bibliotekę, ale jestem jeszcze zbyt początkujący, żeby coś z tego zrozumieć 😄 Ooo panie u mnie to ledwo zalążek jest. 15 minut temu, Krawi92 napisał: Chciałbym jednak postarać się zrozumieć, jak rozbudowywuje się jakieś większe menu, gdzie ustawień może być więcej. Że za pomoca przycisków chodzimy po menu, wracamy do głównego itp. Czy jest to gdzieś jakos fajnie opisane od postaw? Proponuję dowiedzieć się co to są struktury cykliczne, oraz listy jedno i dwukierunkowe. Skrótowo ten temat jest poruszony w książce Tomasza Francuza "Język C dla mikrokontrolerów AVR" Ale tam jest tylko wzmianka o tym. 1 Cytuj Link do komentarza Share on other sites More sharing options...
SOYER Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 (edytowany) Ja jako początkujący teź robiłem takie dość (jak na mnie) rozbudowane menu. Znajdziesz pewnie na Forbocie. Oparte wszystko na switch. Różne poziomy menu to oddzielne funkcje, a wewnątrz funkcji switch pozycje danego poziomu. Generalnie bardzo pomaga, jak kiedyś koledzy podpowiedzieli, graf, maszyna stanów skończonych. Bardzo pomaga. Poczytaj. Edytowano Grudzień 26, 2021 przez SOYER 1 Cytuj Link do komentarza Share on other sites More sharing options...
Krawi92 Grudzień 26, 2021 Autor tematu Udostępnij Grudzień 26, 2021 O właśnie, gdzieś ostatnio słyszałem coś o listach jedno i dwukierunkowych. Czyli do jakiegoś prostego interfejsu nie jest wstydem korzystania po prostu ze switcha? 1 Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
SOYER Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 2 minuty temu, Krawi92 napisał: nie jest wstydem korzystania po prostu ze switcha Nie, z pewnością nie👍. 1 1 Cytuj Link do komentarza Share on other sites More sharing options...
Elvis Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 Jak ma być prosto, to listy raczej niepotrzebne. Używanie switch/case bywa problematyczne jeśli chcemy mieć rozbudowany interfejs. 1 1 Cytuj Link do komentarza Share on other sites More sharing options...
_LM_ Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 (edytowany) 9 minut temu, Krawi92 napisał: Czyli do jakiegoś prostego interfejsu nie jest wstydem korzystania po prostu ze switcha? A pewnie że nie 🙂 Jest tutaj artykuł kol @ethanak o maszynie stanów, doskonale nadaje się do prostych rozwiązań menu. A na moje wypociny w poście o którym wspomniałeś, póki nie będzie konkretnych rozwiązań, to nie patrz bo więcej sobie zaszkodzisz niż pomożesz. Edytowano Grudzień 26, 2021 przez _LM_ 1 Cytuj Link do komentarza Share on other sites More sharing options...
SOYER Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 13 minut temu, Elvis napisał: Używanie switch/case bywa problematyczne jeśli chcemy mieć rozbudowany interfejs. Rozwiń proszę, prostym językiem;), wskaż i uzasadnij alternatywę. Dzięki z góry @Elvis👍. Cytuj Link do komentarza Share on other sites More sharing options...
H1M4W4R1 Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 Ja sobie w wolnej chwili stukam biblioteczkę (aktualnie nie działa pod LCD, a tylko pod PC, ale przerobienie to kwestia napisania odpowiedniej klasy renderera 😉). Tworzenie menu: menu_t* menu2 = (new menu_t()) ->add_option(MENU_SIMPLE_OPTION("1. Tell me a joke \n", funny_text, action_type_t::ON_PRESS)) ->add_option(MENU_BACK_OPTION("2. Back \n"); menu_t* menu1 = (new menu_t()) ->add_option(MENU_SIMPLE_OPTION("1. Select option 2 \n", on_menu_select_2, action_type_t::ON_PRESS)) ->add_option(MENU_SUBMENU_OPTION("2. More... \n", new submenu_action_t(menu2))) ->add_option(MENU_BACK_OPTION("3. Back \n"); menu_t* menu = (new menu_t()) ->add_option(MENU_SIMPLE_OPTION("1. Select option 1 \n", on_menu_select_1, action_type_t::ON_PRESS)) ->add_option(MENU_SUBMENU_OPTION("2. More... \n", new submenu_action_t(menu1))); Oraz użycie: 😉 menu_common_t::open_menu(menu); Dla pytających: typedef enum { ON_PRESS = 1, ON_RELEASE = 2, ON_HOLD = 4, ON_DECREASE = 8, ON_INCREASE = 16, ON_CHANGE = (ON_DECREASE | ON_INCREASE) } action_type_t; Używam action_type, bo pozwala mi na łatwe przesyłanie informacji do menu o tym co się stało w inpucie jednocześnie będąc od niego niezależnym 😉 Tylko to menu jest projektowane pod RP2040, gdzie RAM'u mam pod dostatkiem, więc się tym nie przejmuję... 😛 A tutaj ten tragicznie napisany nieoptymalny kod dla chętnych: menuLib.zip UWAGA: W.I.P. Cytuj Link do komentarza Share on other sites More sharing options...
Elvis Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 Ciężko jest pisać na ekranie, więc odpowiem bardzo krótko - zamiast listy wystarczy tablica. A jej elementami moga być nazwy opcji w menu i funkcje do wywołania - wtedy nie potrzeba ani list, ani długich instrukcji switch. 1 Cytuj Link do komentarza Share on other sites More sharing options...
Krawi92 Grudzień 26, 2021 Autor tematu Udostępnij Grudzień 26, 2021 jeszcze spytam całkiem o coś innego, troszkę odejdę od tematu. Wkleję kod funkcji, który nie działał jak chciałem. void display_menu2(){ ustawiamy_date(); // Tu w formie funkcji wyświetlanie na LCD daty i tekstu "ustaw date" if (!keylock2 && !(PIND & (1<<KEY2))){ // Naciśnięcie klawisza zwiększa dni keylock2=1; czas.DD++; if (czas.DD > 31)czas.DD=0; }else if(keylock2 && (PIND & (1<<KEY2)))keylock2=0; if (!keylock3 && !(PIND & (1<<KEY3))){ // Naciśnięcie klawisza zwiększa miesiące keylock3=1; czas.MM++; if (czas.MM > 12)czas.MM=0; }else if(keylock3 && (PIND & (1<<KEY3)))keylock3=0; if (!keylock4 && !(PIND & (1<<KEY4))){ // // Naciśnięcie klawisza zwiększa dni keylock4=1; czas.YY++; // tu był problem if (czas.YY < 2000).czasYY=2000; }else if(keylock4 && (PIND & (1<<KEY4)))keylock4=0; } Problemem było zwiększanie się roku, bo po naciśnięciu klawisza zmieniała mi się 1 cyfra, czyli było click click, 2000,3000,4000. Doszedłem do wniosku, że chyba chodzi oto, że zmienna czas.YY jest uint16_t, a liczby w AVR są zapisane w formacie little endian, przez co najpierw zapisywany jest młodszy bajt, potem starszy i ja moją operacją zwiększałem ten starszy. Dopiero, gdy odwołałem się do tej zmiennej przez wskaźnik, do zadziałało jak należy. Dopiero od niedawna zacząłem trochę korzystać ze struktur i wskaźników, więc jest jeszcze pewnie niezrozumienie miejscami. Pytanie, czy dobrze kombinuje. A tu funkcja, która działa jak chcę. void display_menu2(Ttime *t){ ustawiamy_date(); if (!keylock2 && !(PIND & (1<<KEY2))){ keylock2=1; czas.DD++; if (czas.DD > 31)czas.DD=0; }else if(keylock2 && (PIND & (1<<KEY2)))keylock2=0; if (!keylock3 && !(PIND & (1<<KEY3))){ keylock3=1; czas.MM++; if (czas.MM > 12)czas.MM=0; }else if(keylock3 && (PIND & (1<<KEY3)))keylock3=0; if (!keylock4 && !(PIND & (1<<KEY4))){ keylock4=1; t->YY++; if (t->YY < 2000)t->YY=2000; }else if(keylock4 && (PIND & (1<<KEY4)))keylock4=0; } Cytuj Link do komentarza Share on other sites More sharing options...
Elvis Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 Jednak musiałem włączyć komputer 🙂 Chodziło mi o opisanie menu strukturą mniej-więcej następującą: typedef void (*menu_func)(void); typedef struct { const char *text; menu_func func; }menu_t; static const menu_t menu1[] = { { "RTC event(?)", RTC_Event }, { "Ustaw date", display_menu2 }, { "Ustaw czas", display_menu }, { "Zapisz zmiany", zapisano_czas }, }; Typ "menu_func" określa funkcje wywoływane po wybraniu opcji - na razie nic nie zwracamy, ani nie ma parametrów. Następnie definiuję typ menu_t, który jest zwykłą parą <nazwa_opcji, funkcja>. Teraz można po prostu utworzyć tablicę, której kolejne pozycje zawierają nazwy do wyświetlenia oraz funkcje do wywołania. Całość jest oznaczona jako "const", używamy więc pamięci flash do przechowywania całości, nie marnujemy RAM-u, ani tym bardziej nie dotykamy sterty. To bardzo uproszczona pierwsza wersja, ale nie wymaga list, switch-y, maszyn stanowych ani innych super zaawansowanych cudów. Jeśli używamy C++ kod aż prosi się o użycie klas, ale ja na razie używam czystego C. 1 Cytuj Link do komentarza Share on other sites More sharing options...
SOYER Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 @_LM_ co Ty n to co napisał @Elvis?? Cytuj Link do komentarza Share on other sites More sharing options...
_LM_ Grudzień 26, 2021 Udostępnij Grudzień 26, 2021 (edytowany) 20 minut temu, SOYER napisał: @_LM_ co Ty n to co napisał @Elvis?? Mówisz o tablicowaniu funkcji? Uważam że to jest świetne rozwiązanie które często stosuję, nie tylko na potrzeby menu i nie tylko z funkcjami. Z resztą nieraz kłóciłem się o to z kol @ethanak Zawsze w większym zbiorze kolejnych parametrów lepiej je wrzucić do tablic. Swoją drogą z palca tego nie wyssałem: klik i klik Edytowano Grudzień 26, 2021 przez _LM_ 1 1 Cytuj Link do komentarza Share on other sites More sharing options...
Krawi92 Grudzień 26, 2021 Autor tematu Udostępnij Grudzień 26, 2021 a ktos odniesie sie do mojego wpisu odbiegajacego od tematu ? nie chce juz zakladac nowego watku 😄 1 Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!