Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.
itemscope itemtype="https://schema.org/QAPage"

[ATMEGA32][C]Jak zrobić proste menu na LCD ? koncepcja

margas4542 23 Paź 2010 22:56 9418 25
  • [ATMEGA32][C]Jak zrobić proste menu na LCD ? koncepcja

    #1
    Poziom 16  

    Witam...z powodu awarii dysku twardego w moim laptopie napisany i działający już program diabli wzięli i obecnie jestem na etapie jego odtwarzania...główne procedury już działają ale mam kłopot z odtworzeniem kodu menu i tu moja prośba do bardziej zaawansowanych w programowaniu kolegów...jak napisać obsługę klawiszy aby nie powtarzać kilkanaście razy np;przejścia do kolejnego ekranu ustawień , obsługi klawisza dodaj 1 do zmiennej X , zatwierdź ustawioną zmienną X , wyjdź z ustawień danego ekranu...w wersji którą utraciłem te procedury powielałem co jednak miało wpływ na wielkość pliku hex..aby zobrazować moją niezbyt jednak udaną koncepcję wklejam zalążek kodu..

    Code:

    //-----koniec odczytu daty i czasu     
       }
       }
       if(!(PIND & _BV(4)))      //jeżeli "0" to ustaw znacznik na "0"
       {
       _delay_ms(20);
        PORTA |=_BV(6);         //znacznik zezwolenia na wejście do menu
        PORTB |=_BV(0);         //podświetlenie LCD PORTB pin 1
       }
    //-----LCD menu
       if(!(PINA & _BV(6)))    //jeżeli nie ustawiony to ominięcie menu
       {
    //-----WYŚWIETLANIE-----DANYCH
        LCD_GoTo(1,0);  LCD_WriteText(itoa(data_dd,buffer_t,10));   //dziesiątki dni
        LCD_GoTo(2,0);  LCD_WriteText(itoa(data_jd,buffer_t,10));   //jednostki dni
        LCD_GoTo(3,0);  LCD_WriteText("-");
        LCD_GoTo(4,0);  LCD_WriteText(itoa(data_dm,buffer_t,10));   //dziesiątki miesięcy
        LCD_GoTo(5,0);  LCD_WriteText(itoa(data_jm,buffer_t,10));   //jednostki miesięcy
        LCD_GoTo(6,0);  LCD_WriteText("-");
        LCD_GoTo(7,0);  LCD_WriteText("10");
        LCD_GoTo(11,0);  LCD_WriteText(itoa(czas_hh,buffer_t,10));   //jednostki godzin
        LCD_GoTo(12,0);  LCD_WriteText(itoa(czas_h,buffer_t,10));   //dziesiatki godzin
        LCD_GoTo(13,0);  LCD_WriteText(":");                  //dwukropek
        LCD_GoTo(14,0);  LCD_WriteText(itoa(czas_mm,buffer_t,10));   //jednostki minut
        LCD_GoTo(15,0);  LCD_WriteText(itoa(czas_m,buffer_t,10));   //dziesiatki minut
        LCD_GoTo(16,0);  LCD_WriteText(":");                  //dwukropek
        LCD_GoTo(17,0);  LCD_WriteText(itoa(czas_ss,buffer_t,10));   //jednostki sekund
        LCD_GoTo(18,0);  LCD_WriteText(itoa(czas_s,buffer_t,10));   //dziesiatki sekund
        LCD_GoTo(0,1);   LCD_WriteText("AKU");
        LCD_GoTo(4,1);   LCD_WriteText(dtostrf(aku=aku,4,1,buffer_n));//napięcie akumulatora
        LCD_GoTo(8,1);   LCD_WriteText("V");
        LCD_GoTo(10,1);  LCD_WriteText("SOL");
        LCD_GoTo(14,1);  LCD_WriteText(dtostrf(sol=sol,4,1,buffer_n));//napięcie solara
        LCD_GoTo(18,1);  LCD_WriteText("V");
        LCD_GoTo(21,0);  LCD_WriteText(status); 
        LCD_GoTo(20,1);  LCD_WriteText(dtostrf(lad=lad,4,1,buffer_n));//prąd ładowania
        LCD_GoTo(24,1);  LCD_WriteText("A");
        LCD_GoTo(28,0);  LCD_WriteText("AKUM");
        LCD_GoTo(27,1);  LCD_WriteText(dtostrf(inpower=inpower,4,1,buffer_n));//prąd akumulatora
        LCD_GoTo(31,1);  LCD_WriteText("A");
        LCD_GoTo(35,0);  LCD_WriteText("OBCI");
        LCD_GoTo(34,1);  LCD_WriteText(dtostrf(out=out,4,1,buffer_n));//prąd obciążenia(obwody 12V)
        LCD_GoTo(38,1);  LCD_WriteText("A");
       goto end;
       }
       unsigned char key;
       if(!(PIND & _BV(4)))
       { 
       _delay_ms(200);
        LCD_GoTo(0,0);  LCD_WriteText(info[0]);
        LCD_GoTo(0,1);  LCD_WriteText(info[0]);
       key++;
       if(key>6)
       {
        key=0;
       }
        switch(key)
       {
        case 0://------------------------------------0
        while(1)
        {
          LCD_GoTo(0,0);  LCD_WriteText("EKRAN 0");
         if(!(PIND & _BV(4)))   //jeżeli ustawiony to następny ekran
         {
          key=1;
          goto exit_1;
         }
          if(!(PIND & _BV(4)))    //jeżeli ustawiony to wejście do ustawię ekran 0
         _delay_ms(30);
         {
          while(1)
          {
            LCD_GoTo(0,0);      LCD_WriteText("USTAWIENIA   ");
            if(!(PIND & _BV(5)))
          {
           set_hh++;
             LCD_GoTo(10,1);   LCD_WriteText(dtostrf(set_hh,2,0,buffer_t));//wyś nastawę
           if(set_hh>23)
           {
            set_hh=0;
           }
          }
            if(!(PIND & _BV(6)))
          {
           set_mm++;
             LCD_GoTo(13,1);   LCD_WriteText(dtostrf(set_mm,2,0,buffer_t));//wyś nastawę
           if(set_hh>59)
           {
            set_mm=0;
           }
          }
            if(!(PIND & _BV(7)))
            _delay_ms(30);
           {
           while(!(PIND & _BV(7)))
            _delay_ms(30);
             {
              LCD_GoTo(20,1);   LCD_WriteText("WYJSCIE / ZAPIS ");
            //zapis np; scalaka zegarka lub pamięć zewnętrzna
              _delay_ms(2000);
              key=1;
             goto exit_1;//wyjście z pętli
           }
           }
          }
         }
        }
        {}exit_1:
         break;
         case 1://------------------------------------1
          LCD_GoTo(0,0);  LCD_WriteText("EKRAN 1");
         break;
         case 2://------------------------------------2
          LCD_GoTo(0,0);  LCD_WriteText("EKRAN 2");
         break;
         case 3://------------------------------------3
          LCD_GoTo(0,0);  LCD_WriteText("EKRAN 3");
         break;
         case 4://------------------------------------4
          LCD_GoTo(0,0);  LCD_WriteText("EKRAN 4");
         break;
         case 5://------------------------------------5
          LCD_GoTo(0,0);  LCD_WriteText("EKRAN 5");
         break;
         case 6://------------------------------------6
          LCD_GoTo(0,0);  LCD_WriteText("EKRAN 6");
         break;
    //------------------------------------------------end
        }
       {}end:
       }
      }
     return;
    }//end main
    //********** END MAIN **********

    0 25
  • #2
    Poziom 38  

    Kod przykładowy dla butterfly na stronie atmela. I na avrfreaks też widziałem kilka koncepcji menu wielopoziomowego.

    0
  • #3
    Poziom 16  

    Butterfly tinymenu micromenu ok znam tylko mija wiedza programistyczna to nie wysokie loty potrzebuje nie tyle menu wielopoziomowego co przełączanego na kolejne ekrany , ustawienia co trzeba i wyjścia....proste i funkcjonalne i na mój poziom zaawansowania w C...żebym wiedział jak działa a nie patrzył na kod niczym chiński tekst...

    0
  • #4
    Poziom 31  

    Zastosuj zmienną liczbową. Każda liczba to inny poziom menu (inny ekran). Prosta i szybka nawigacja z każdego miejsca do każdego miejsca.

    0
  • #5
    Poziom 16  

    OK..łatwiej byłoby ułożyć kostkę Rubika...nie mam pojęcia jak to napisać..próbuje coś takiego..

    Code:

    //-----koniec odczytu daty i czasu     
       }
       }
       if(!(PIND & _BV(4)))
       {
        loop_until_bit_is_set(PIND,4);
        PORTA |= _BV(6);
       PORTB |= _BV(0);
       }
       if(!(PINA & _BV(6)))            //jeżeli naciśnięty
       {
    //-----ekran główny wyświetlanie danych
    //
    //-----koniec ekranu głównego
       }
       else
       {
       if(!(PIND & _BV(4)))
       {
        loop_until_bit_is_set(PIND,4);
        LCD_GoTo(0,0);  LCD_WriteText(info[0]);
    //    LCD_GoTo(0,1);  LCD_WriteText(info[0]);
       ekran_menu++;
        {
        if(ekran_menu>5)
        {
        ekran_menu=1;
        }
        switch(ekran_menu)
        {
        case 1://------------------------------------1
         LCD_GoTo(0,0);  LCD_WriteText("EKRAN 1");
         break;
         case 2://------------------------------------2
         LCD_GoTo(0,0);  LCD_WriteText("EKRAN 2");
         break;
         case 3://------------------------------------3
         LCD_GoTo(0,0);  LCD_WriteText("EKRAN 3");
         break;
         case 4://------------------------------------4
         LCD_GoTo(0,0);  LCD_WriteText("EKRAN 4");
         break;
         case 5://------------------------------------5
         LCD_GoTo(0,0);  LCD_WriteText("EKRAN 5");
         break;
         case 6://------------------------------------6
         LCD_GoTo(0,0);  LCD_WriteText("EKRAN 6");
         break;
         }
        }
       }
      }
     return;
    }//end main
    //********** END MAIN **********

    0
  • #6
    Poziom 31  

    Przyciskami zmniejszasz/zwiększasz liczbę. Warunkami IF obsługujesz dany poziom menu - na który wskazuje liczba.

    0
  • #7
    Poziom 16  

    Same instrukcje warunkowe if się nie sprawdzą ponieważ w normalnym trybie pracy [wyświetlanie pomiarów i innych danych] menu nastaw ma być pomijane przez program a w chwili wejścia do menu pomijany będzie ekran główny...uważam że nie ma sensu sprawdzać tysiące razy na dobę każdego if-a menu z którego będzie się korzystać np;raz dziennie aby załączyć lub wyłączyć jeden z czterech obwodów o ile będzie taka potrzeba.....

    0
  • Pomocny post
    #8
    Poziom 38  

    Szybki wstęp to takiego menu:

    Oznaczamy na potrzeby programu każdą pozycję w menu:

    Code:
     enum{ 0, menu1, menu2, menu3, menu11, menu12, ...};


    tworzymy tablicę przejść menu
    Code:
    unsigned char menu_stage [32][4] PROGMEM = {
    
    // next  prev  up down
    {0,0,0,0};
    {};
    {};
    {};
    {};
    }
    nieistotne pola wypełniamy zerem, lub tak by dane menu przechodziło samo na siebie. Kolejność wierszy musi być zgodna z wyliczeniem enum

    Tworzymy wskaźniki do napisów menu

    Code:
    char *menu_text [32] PROGMEM= {
    
    0;
    text_menu1;
    text_menu2;
    ...
    };


    Tworzymy tablicę wskaźników do funkcji menu:
    Code:
    void *menu_function[32] PROGMEM =
    
    {
    0;
    func_menu1;
    .....
    }


    Napisy oraz funkcje należy wcześniej zdeklarować.

    DO obsługi menu będą nam potrzebne następujące zmienne:

    Code:
    unsigned char menu = stan początkowy; // zawiera wartość odpowiadającą bieżącej pozycji w menu.
    
    void (* funkcja)(void);  // Wskaźnik do funkcji. Pozwala na wywoływanie rożnych funkcji z jednym miejscu bez konieczności stosowania ifów.


    Obsługa menu przyciskami esc enter next prev

    do
    {
    oczekuje na wciśnięcie przycisku

    jeśli wciśnięto przycisk enter oraz wskaźnik w tablicy menu_function[menu] !=0 to
    przepisz zawartość komórki tej tablicy do wskaźnika do funkcji i wywołaj funkcję.

    Następnie przechodzimy do odpowiedniej funkcji menu:

    odczytujemy wartość tablicy menu_stage [menu][przycisk]
    sprawdzamy czy != 0
    Przepisujemy odczytaną wartość do zmiennej menu
    drukujemy napis z tablicy napisów popierając odpowiedni wskaźnik.

    }

    1
  • #9
    Poziom 16  

    No i załatwiłem się na cacy...namieszałem jak królik w kapuście i cały program się sypie przez to całe pseudo-menu...nie dosyć że straciłem dysk i działający program to teraz jak na złość będę siedział nad jego odtworzeniem nie wiem jak długo usiłując sobie przypomnieć jak to napisałem...

    0
  • #10
    Użytkownik usunął konto  
  • #11
    Poziom 16  

    Albo jestem za stary albo za bardzo zmęczony...jak komuś się chce pokombinować to wklejam trochę kodu..może z tego chaosu zrobi jakieś logiczne MENU LCD..

    Code:

    // koniec pomiarów odczytu daty monitorowania napięć i innych procedur -:)
        unsigned char kanal=10;
        for(kanal=10; kanal<18; kanal++)   
        {   
         switch(kanal)
         {
         case 10://czasu włącz/wyłącz dla kanalu 1
         //sprawdż status - jeżeli manual to pomiń dalsze sprawdzanie
         //jeżeli auto to sprawdz dzień tygodnia
         //jeżeli nie ten dzień tygodnia to pomiń dalsze sprawdzanie
         //jeżeli dzień zgodny z nastawą to sprawdz godzine,minute
         //jeżeli godzina i minuta zmienna[1][2][3][4] zgodna z nastawą godzina minuta
         //to wykonaj określoną czynność [włącz lub wyłącz kanał]
         break;
         case 11://czas do włączenia kanal 2
         break;
         case 12://czas do włączenia kanal 3
         break;
         case 13://czas do włączenia kanal 4
         break;
         case 14://czas do wyłączenia kanal 1
         break;
         case 15://czas do wyłączenia kanal 2
         break;
         case 16://czas do wyłączenia kanal 3
         break;
         case 17://czas do wyłączenia kanal 4
         break;
         default:
         break;
        }
       }
       unsigned int ekran_menu;
       if(!(PIND & _BV(4)))
       {
        loop_until_bit_is_set(PIND,4);
       PORTB |= _BV(0);   //włącza podświetlenie LCD
       {
        if(!(PIND & _BV(4)))
       {
         loop_until_bit_is_set(PIND,4);
         _delay_ms(10);
         ekran_menu++;
         if(ekran_menu>6)   
        {
         ekran_menu=0;
         }
        }
       if(ekran_menu==0)
       {
       LCD_GoTo(1,0);   LCD_WriteText(itoa(data[0],buffer_t,10));
       LCD_GoTo(2,0);   LCD_WriteText(itoa(data[1],buffer_t,10));
       LCD_GoTo(3,0);   LCD_WriteText("-");
       LCD_GoTo(4,0);   LCD_WriteText(itoa(data[2],buffer_t,10));
       LCD_GoTo(5,0);   LCD_WriteText(itoa(data[3],buffer_t,10));
       LCD_GoTo(6,0);   LCD_WriteText("-");
       LCD_GoTo(7,0);   LCD_WriteText("10");
       LCD_GoTo(11,0);  LCD_WriteText(itoa(rtc[0],buffer_t,10));//jednostki godzin
       LCD_GoTo(12,0);  LCD_WriteText(itoa(rtc[1],buffer_t,10));//dziesiatki godzin
       LCD_GoTo(13,0);  LCD_WriteText(":");                  //dwukropek
       LCD_GoTo(14,0);  LCD_WriteText(itoa(rtc[2],buffer_t,10));//jednostki minut
       LCD_GoTo(15,0);  LCD_WriteText(itoa(rtc[3],buffer_t,10));//dziesiatki minut
       LCD_GoTo(16,0);  LCD_WriteText(":");                  //dwukropek
       LCD_GoTo(17,0);  LCD_WriteText(itoa(rtc[4],buffer_t,10));//jednostki sekund
       LCD_GoTo(18,0);  LCD_WriteText(itoa(rtc[5],buffer_t,10));//dziesiatki sekund
       LCD_GoTo(0,1);   LCD_WriteText("AKU");
       LCD_GoTo(4,1);   LCD_WriteText(dtostrf(aku=aku,4,1,buffer_n));
       LCD_GoTo(8,1);   LCD_WriteText("V");               //napięcie akumulatora
       LCD_GoTo(10,1);  LCD_WriteText("SOL");
       LCD_GoTo(14,1);  LCD_WriteText(dtostrf(sol=sol,4,1,buffer_n));
       LCD_GoTo(18,1);  LCD_WriteText("V");               //napięcie solara
       LCD_GoTo(21,0);  LCD_WriteText(status); 
       LCD_GoTo(20,1);  LCD_WriteText(dtostrf(lad=lad,4,1,buffer_n));
       LCD_GoTo(24,1);  LCD_WriteText("A");               //prąd ładowania
       LCD_GoTo(28,0);  LCD_WriteText("AKUM");
       LCD_GoTo(27,1);  LCD_WriteText(dtostrf(inpower=inpower,4,1,buffer_n));
       LCD_GoTo(31,1);  LCD_WriteText("A");               //prąd akumulatora
       LCD_GoTo(35,0);  LCD_WriteText("OBCI");
       LCD_GoTo(34,1);  LCD_WriteText(dtostrf(out=out,4,1,buffer_n));
       LCD_GoTo(38,1);  LCD_WriteText("A");              //prąd obciążenia(obwody 12V)
       if(!(PINA & _BV(7)))
       {
        _delay_ms(30);
        PORTB ^=_BV(0);   //podświetlenie LCD
        _delay_ms(30);
       }
         LCD_GoTo(0,0);       LCD_WriteText("KANAL 1    ");
         LCD_GoTo(0,1);       LCD_WriteText("STATUS");
         LCD_GoTo(8,1);       LCD_WriteText(kanal[0]);
         LCD_GoTo(14,1);   LCD_WriteText(tryb_pracy[0]);
         LCD_GoTo(20,0);   LCD_WriteText("CZAS  ZALACZ WYLACZ");
         LCD_GoTo(20,1);   LCD_WriteText(itoa(rtc[0],buffer_t,10));
         LCD_GoTo(21,1);   LCD_WriteText(itoa(rtc[1],buffer_t,10));
         LCD_GoTo(22,1);   LCD_WriteText(":");
         LCD_GoTo(23,1);   LCD_WriteText(itoa(rtc[2],buffer_t,10));
         LCD_GoTo(24,1);   LCD_WriteText(itoa(rtc[3],buffer_t,10));
        //czas załączenia
         LCD_GoTo(26,0);   LCD_WriteText(itoa(set_time[0],buffer_t,10));
         LCD_GoTo(27,0);   LCD_WriteText(itoa(set_time[1],buffer_t,10));
         LCD_GoTo(28,0);   LCD_WriteText(":");
         LCD_GoTo(29,0);   LCD_WriteText(itoa(set_time[2],buffer_t,10));
         LCD_GoTo(30,0);   LCD_WriteText(itoa(set_time[3],buffer_t,10));
         //czas wyłączenia
         LCD_GoTo(32,1);   LCD_WriteText(itoa(set_time[4],buffer_t,10));
         LCD_GoTo(33,1);   LCD_WriteText(itoa(set_time[5],buffer_t,10));
         LCD_GoTo(34,1);   LCD_WriteText(":");
         LCD_GoTo(35,1);   LCD_WriteText(itoa(set_time[6],buffer_t,10));
         LCD_GoTo(36,1);   LCD_WriteText(itoa(set_time[7],buffer_t,10));
       }
        if(ekran_menu==2)://----------NASTAWY CZASU WŁ/WYŁ KANAŁ 2
        {
         LCD_GoTo(0,0);  LCD_WriteText("EKRAN 2");
        }
        if(ekran_menu==3)://----------NASTAWY CZASU WŁ/WYŁ KANAŁ 3
        {
        LCD_GoTo(0,0);  LCD_WriteText("EKRAN 3");
        }
        if(ekran_menu==4)://----------NASTAWY CZASU WŁ/WYŁ KANAŁ 4
       {
         LCD_GoTo(0,0);  LCD_WriteText("EKRAN 4");
        }
        if(ekran_menu==5)
        {
         LCD_GoTo(20,0); LCD_WriteText("Aktualna data");
         LCD_GoTo(34,0); LCD_WriteText(itoa(data[0],buffer_t,10));
        LCD_GoTo(35,0); LCD_WriteText(itoa(data[1],buffer_t,10));
        LCD_GoTo(36,0); LCD_WriteText("/");
        LCD_GoTo(37,0); LCD_WriteText(itoa(data[3],buffer_t,10));
        LCD_GoTo(38,0); LCD_WriteText(itoa(data[4],buffer_t,10));          
         if(!(PIND & _BV(5)))
         {
          if(++data[0] >= 13)
         {
          data[0]++;
           data[0] = 0;
          }
        }
        if(!(PIND & _BV(6)))
         {
          if(++data[1] >= 32)
         {
          data[1]++;
           data[1] = 0;
          }
        }
         LCD_GoTo(20,1); LCD_WriteText("Ustaw date");
        LCD_GoTo(34,1); LCD_WriteText(itoa(data[0],buffer_t,10));
        LCD_GoTo(36,1); LCD_WriteText("/");
        LCD_GoTo(37,1); LCD_WriteText(itoa(data[1],buffer_t,10));
        LCD_GoTo(38,1); LCD_WriteText("/");
        {                        //zapis nastawionej daty do PCF8583
          TWI_write(zegar,0x05,data[0]);   
          TWI_write(zegar,0x06,data[1]);           
         _delay_ms(50);
         }
        }
        if(ekran_menu==6)
        {//----------NASTAWY CZASU ZEGARA
         LCD_GoTo(0,0);  LCD_WriteText("Aktualny czas");
        LCD_GoTo(6,1);  LCD_WriteText(itoa(rtc[0],buffer_t,10));
        LCD_GoTo(7,1);  LCD_WriteText(itoa(rtc[1],buffer_t,10));
        LCD_GoTo(8,1);  LCD_WriteText(":");
        LCD_GoTo(9,1);  LCD_WriteText(itoa(rtc[2],buffer_t,10));
        LCD_GoTo(10,1); LCD_WriteText(itoa(rtc[3],buffer_t,10));
        LCD_GoTo(11,1); LCD_WriteText(":");
        LCD_GoTo(12,1); LCD_WriteText(itoa(rtc[4],buffer_t,10));
        LCD_GoTo(13,1); LCD_WriteText(itoa(rtc[5],buffer_t,10));      
         if(!(PIND & _BV(5)))
         {
          if(++rtc[0] >= 24)
         {
          set_rtc[0]++;
           set_rtc[0] = 0;
          }
        }
        if(!(PIND & _BV(6)))
         {
          if(++set_rtc[2] >= 60)
         {
          set_rtc[1]++;
           set_rtc[1] = 0;
          }
        }
         LCD_GoTo(20,0); LCD_WriteText("Ustaw czas");
        LCD_GoTo(26,1); LCD_WriteText(dtostrf(set_rtc[0],2,0,buffer_n));
        LCD_GoTo(28,1); LCD_WriteText(":");
        LCD_GoTo(29,1); LCD_WriteText(dtostrf(set_rtc[1],2,0,buffer_n));
        LCD_GoTo(31,1); LCD_WriteText(":00");
         if(!(PIND & _BV(7)))
        {                        //zapis nastawionego czasu do PCF8583
          TWI_write(zegar,0x04,set_rtc[0]); //       
          TWI_write(zegar,0x03,set_rtc[2]);   //
          TWI_write(zegar,0x02,0x00);   
         _delay_ms(50);
         }
       }
      }
     }
    }
     return;
    }
    //********** END MAIN **********

    0
  • #12
    Poziom 38  

    Najnormalniejszy był pomysł tadzika, nie sprawdzasz 10 000 0000 0000 0000 warunków, tylko wywołujesz różne funkcje, do których wskaźniki masz napisane w pamięci, i poprzez naciśnięcie przycisku (nie wiem jak to tam masz porobione) wywołanie odpowiedniej funkcji

    0
  • #13
    Użytkownik usunął konto  
  • #14
    Poziom 27  

    Jak się kolega zapozna ze strukurami, wskaźnikami i manipulacją wskaźnikami to się okaże że wielopoziomowe menu robi się trywialne. Jeśli masz do dypozycji odpowiednio dużo pamięci to służe na PW gotowcem o w zasadzie nieograniczonej ilośći zagnieżdżeń.

    0
  • #15
    Poziom 38  

    Koledzy nie chwalcie tak mnie. Ja tylko ulepszyłem menu z butterfly usuwając przeglądanie całej tablicy w poszukiwaniu odpowiedniej pozycji. Kod dzięki temu jest bardziej przejrzysty i prostszy, ale kosztem trudności pisania, niestety trzeba pilnować pozycji w tablicach. Dobrze jest enum napisać w pionie, każda pozycja w nowej linii, następnie skopiowanie niżej skomentowanie każdej linii i uzupełnianie tablic.

    0
  • #16
    Poziom 16  

    No teraz to dobiliście mnie totalnie...dwa miesiące temu kupiłem płytkę EvB z atmegą 32 na pokładzie i zacząłem drążyć C od ponad półtora miesiąca usiłuje napisać JEDEN program ale jak nie chochliki to złośliwość losu...albo dokumentacja po angielsku....bez pomocy nigdy go nie skończę....

    0
  • #17
    Poziom 38  

    margas4542 napisał:
    ...albo dokumentacja po angielsku..


    Nie ma zlituj kiedyś tego angielskiego trzeba się nauczyć. W dodatku do czytania dokumentacji wystarczą podstawy. Wiele określenie technicznych brzmi podobnie. Poza tym są pełne rysunków i tabelek ;p. A w dobie translatorów to już zupełnie. Więc nie odrzucaj dokumentacji tylko czytaj, przeglądaj, aby dostać wprawy i rozeznania jak z "tego czegoś" korzystać. Bez tego ani rusz.

    0
  • #18
    Poziom 16  

    Coś potrafię "wyczytać" z angielskiej dokumentacji ale zrozumienie przychodzi trudniej...np; PCF8583...czytałem kombinowałem i marnie szło i dopiero gdy zobaczyłem dobrze napisany kod obsługi I2C dla PCF-a pozwalający na odczyt czasu i daty i porównałem z tabelkami w dokumentacji zacząłem dochodzić jak to funkcjonuje...i z ustawieniem a potem zapisem nowego czasu i daty nie miałem kłopotu....niestety jestem wzrokowcem i oby zrozumieć muszę sobie wyobrazić jak coś funkcjonuje a w przypadku C jeszcze przypomnieć czego uczyłem się na lekcjach matematyki ponad trzydzieści parę lat temu...

    0
  • Pomocny post
    #19
    Poziom 35  

    Te wasze kombinacje z menu to jakiś koszmar.

    za ILOSC_PODMENU trzeba wstawić liczbę taką, ile podmenu ma mieć
    dane "menu"..

    Code:

    typedef struct _tMenuItem
    {
    unsigned char *tekst;
    void *menuItems[ILOSC_PODMENU];
    unsigned char items,savedIndex;
    } tMenuItem;


    [ATMEGA32][C]Jak zrobić proste menu na LCD ? koncepcja

    Teraz wystarczy zrobić:

    - funkcję, ktora pobierze wskaźnik na tMenuItem, i będzie wyświetlać zawartość
    tMenuItema spod ((tMenuItem*)(((tMenuItem*)wskaznik)->items[index]))->tekst (zakładając, że "index" to numer screena w danym (pod)menu... )

    - stos wskaźników na tMenuItem

    - przy kaźdym enter/dalej/ok sprawdzamy, czy ((tMenuItem*)(((tMenuItem*)wskaznik)->items[index]))->items !=0, jeśli tak, to bieżąco wyświetany screen (menu), ma jakieś podmenu, a jeśli nie, to wykonać cośtam (zależne od wybranego menu).
    Jeśli bieżący screen ma podmenu, to:
    1) zachować bieżący index do savedIndex
    2) wepchnąć na stos wskaźnik bieżącego menu
    3) Zmienić wskaźnik bieżącego menu na ((tMenuItem*)(((tMenuItem*)wskaznik)->items[index]))
    4) i wyzerować glowny index

    - przy każdym wróc/powrót/wstecz/cancel:
    1) zdjąć ze stosu wskaznik na tMenuItem
    2) Ustawić wskaznik biezacego menu na ten wskaznik zdjety ze stosu
    3) ustawic glowny index na index spod tego wskaznika

    Gdy zachce się od razu przypisywac rozne funkcje dla roznych akcji kazdego z tMenuItem-ow, to można rozszerzyć typ o np.
    Code:

    void *(*OnKbOK)(void*);
    void *(*OnKbUp)(void*);
    void *(*OnKbDown)(void*);
    void *(*OnKbLeft)(void*);
    void *(*OnKbRight)(void*);

    Przyklad dotyczy tutaj standardowej 5przyciskowej nawigacji (góra, dół, lewo, prawo, OK)

    Do takich funkcji można oczywiście podawać (a nawet powinno się) wskaznik na tMenuItem-a, który akcję wywołał - dla funkcji współdzielonych między wiele menuItem-ow. Funkcje które są specyficzne dla konkretnego menuItem-a, nie muszą przyjmować żadnego argumentu i również nie muszą nic zwracać.

    -----------------------
    Za poplątane casty przepraszam, moglem gdzies przegiąć z nawiasami :] Edytor tekstu na elce nie podświetla nawiasów :P

    1
  • #20
    Poziom 16  

    Aleście mi zabili klina...od kliku godzin próbuje to ugryźć i chyba się poddam bo jak na razie niewiele zdziałałem...czy można to przełożyć na prostszy język ?

    0
  • Pomocny post
    #21
    Poziom 35  

    Tak ;] na assembler

    1
  • #22
    Poziom 16  

    Dobry dowcip...piątka z plusem....a tak poważnie struktury , wskaźniki i cały ten hokus-pokus z nimi to bardzo wysoka półka i jeszcze dużo wody w Wiśle upłynie zanim choć trochę załapie o co w tym chodzi....

    0
  • #23
    Poziom 38  

    Wskaźnik to taki paluszek, który na coś pokazuje. W tym przypadku wskazuje na różne teksty. Struktura to powiązany ze sobą zbiór zmiennych. I tak w najprostszym sensie należy to wszystko rozumieć. Należy z tego korzystać bo zamiast 100 tysięcy linii kodu zrobi Ci się ich pięć.

    Ja mogę prościej napisać to o czym mówił nsvinc w kodzie maszynowym jeżeli chcesz

    0
  • #24
    Poziom 16  

    Ja wiem że wszystko jest proste ja się rozumie o czym mówi...ja tego nie łapie nie wiem co z czym połączyć gdzie zdefiniować wskaźniki a gdzie odwołania gdzie ma być obsługa klawiszy a gdzie inne czary mary...znalazłem kod z tinymenu aby zobaczyć jak tam to zrobione ale adaptacja kodu do programu przerasta moje możliwości..

    0
  • Pomocny post
    #25
    Poziom 38  

    Twoim problemem jest nieznajomość podstaw języka a nie niewiedza jak napisać menu widzę :) może kup sobie jakąś książkę do C ? albo ściągnij z internetu bo są też darmowe książki Polecam także poczytać standard C, manuale etc.

    1
  • #26
    Poziom 16  

    Nie przeczę i nie ukrywam że orłem nie jestem i potykam się o kamyczki ale czy po przeczytaniu czymś tam od razu wiadomo jak to zrobić?..nie do końca bo dopiero w praktyce wychodzi ile się zrozumiało z tekstu manuala czy ksiązki..

    Dodano po 4 [godziny] 42 [minuty]:

    Mimo wszystko pomogliście mi podtrzymując na duchu za co bardzo dziękuje...napisałem obsługę tego menu standardowo na switchu na zasadzie przełączania do kolejnego ekranu i po osiągnięciu ostatniego powrót do pierwszego...takie kółeczko. Na kolejnych ekranach ustawiam czas i datę zegarka a potem wypycham do PCF8583 oraz ustawiam czasy timera włącz/wyłącz dla każdego z 4 kanałów [obwody 230V] niezależnie...jeszcze muszę tylko dopisać procedurę zapisu nastaw timera do pamięci PCF-a lub EEPROMU 24C02...coś wykombinuje.Pozdrawiam.

    0