Wielopoziomowe menu.

Pytania, kody i porady dotyczące nie tylko Bascom.
ODPOWIEDZ
przemek6
Posty: 2
Rejestracja: 16 lut 2016, 18:42

Wielopoziomowe menu.

Post autor: przemek6 » 16 lut 2016, 19:01

Cześć wszystkim.
Jestem w trakcie projektowania pewnego urządzenia i mam problem z utworzeniem wielopoziomowego menu.
Znalazłem program "LCD Menu" ze strony klik.
U mnie jednak nie ma enkodera oraz nie będę używał przerwania.
Do tego mogę przeznaczyć piny: .F0, .F1, .F2 i .F3 (Atmega128).



Przy linijce "Menu_init" wywala błąd, więc dałem to jako komentarz.
Mam też inną konfigurację LCD- "lcd4busy_anypin" więc z przykładu została usunięta.
Po skompilowaniu programu z własnym menu- wchodzę do niego (udało mi się go scalić)- użyłem warunek if PINF.0 ... zamiast przerwania.
Nie wychodzi mi przerobienie tego enkodera na przyciski.
Na końcu postu wklejam kod przykładu z tej strony.

Serdecznie dziękuję i pozdrawiam,
Przemek

Kod: Zaznacz cały

$regfile = "m32def.dat"
$crystal = 16000000
$baud = 57600

$hwstack = 64
$swstack = 48
$framesize = 64

Const False = 0 : Const True = 1


'###############################################################################
'##      R O T A R Y   E N C O D E R                                          ##
'###############################################################################
Encoder_a Alias Pinb.1
Encoder_switch Alias Pind.6
Portb.1 = True                                              ' pullup encoder a,
Portb.2 = True                                              ' encoder b,
Portd.6 = True                                              ' and encoder switch
Config Int2 = Falling                                       ' encoder b is the interrupt source
On Int2 Encoder_isr
Enable Int2
Dim Encoder_switch_old As Bit
Dim Encoder_turn_left As Byte , Encoder_turn_right As Byte


'###############################################################################
'##      T I M E R                                                            ##
'###############################################################################
Const Ticker_hwtimer = 0                                    ' Choose which hardware timer to use
Const Ticker_frequency = 1000                               ' set the timer resolution
Const Tickers = 1                                           ' # of software timers to use
$include "inc\tickers.bas"
Const Timer_readswitches = 1


'###############################################################################
'##      L C D                                                                ##
'###############################################################################
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.2 , Rs = Portc.3


'###############################################################################
'##      L C D   M E N U                                                      ##
'###############################################################################
Macro Menu_include_data
   ' include the data file created with the menu designer
   $include "menu_data_simple.bas"
End Macro
$include "inc\menu.bas"


'###############################################################################
'##      V A R I A B L E S                                                    ##
'###############################################################################
Dim Tempbyte As Byte


'###############################################################################
'##      I N I T                                                              ##
'###############################################################################
Encoder_switch_old = Encoder_switch

Ticker_time(timer_readswitches) = 20                        ' 20 ms debounce
Ticker_enabled(timer_readswitches) = True

Menu_init

Enable Interrupts
Gosub Draw_homescreen


'###############################################################################
'##      M A I N   L O O P                                                    ##
'###############################################################################
Do
   ' one function to rule them all
   Menu

   Select Case Ticker_get_interrupt()
   Case Timer_readswitches:
      ' encoder switch pressed?
      If Encoder_switch = True And Encoder_switch_old = False Then
         Tempbyte = Menu_enter()
         Select Case Tempbyte
         Case Menu_exit:                                    ' menu closed
            Gosub Draw_homescreen

         End Select
      End If
      Encoder_switch_old = Encoder_switch

      ' encoder turns left
      If 0 < Encoder_turn_left Then
         Decr Encoder_turn_left
         Menu_backward
      End If

      ' encoder turns right
      If 0 < Encoder_turn_right Then
         Decr Encoder_turn_right
         Menu_forward
      End If
   End Select
Loop


'###############################################################################
'##      S U B R O U T I N E S                                                ##
'###############################################################################
Draw_homescreen:
   Cls
   Cursor Off
   Locate 1 , 1
   Lcd "  LCD MENU 1.1"
   Locate 2 , 1
   Lcd "    Sample 1"
Return

Encoder_isr:
   ' to use with a rotary encoder
   If Encoder_a = False Then
      Incr Encoder_turn_right
   Else
      Incr Encoder_turn_left
   End If
Return
Awatar użytkownika
niveasoft
Posty: 1216
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Wielopoziomowe menu.

Post autor: niveasoft » 16 lut 2016, 19:21

Witam.

To nie jest akurat skomplikowane. Często używam tak skonstruowanego enkodera bo napisany jest lekko a nie gubi zdarzeń.
Zadeklarowane są dwie zmienne Encoder_turn_left i Encoder_turn_right i tylko te zmienne są powiększane w obsłudze przerwania i natychmiast następuje powrót. Te zmienne sa sprawdzane w pętli głównej i jeśli któraś jest większa od zera to wykonywana jest żądana akcja a zmienna zmniejszana. Potem jeśli ktos szybciej pokreci enkoderem to ilość klików się kumuluje a w kodzie w pętli głównej po prosu akcje będa sie dokonywały aż do momentu aż wartości zmiennych spadną do zera. Można by napisac taki kod że jeśli ktoś pokrecił w lewo a potem zaraz w prawo żeby sie wartosci znosiły...no ale nie będę gdybał tylko przejde do rozwiązania.

Żeby za dużo nie zmieniac to możesz po prostu tam gdzie sprawdzasz przyciski zwiększać zmienne Encoder_turn_left i Encoder_turn_right. Kod juz sam zareaguje bo w pętli napisane jest: ' encoder turns left If 0 < Encoder_turn_left Then Decr Encoder_turn_left Menu_backward End If ' encoder turns right If 0 < Encoder_turn_right Then Decr Encoder_turn_right Menu_forward End If
Czyli spróbuj coś na wzór: "Jeśli przycisk = 0 Then Incr Encoder_turn_right"

Obsługe przerwania z enkodera możesz wtedy usunąć całkiem.
Równie dobrze możesz tam gdzie sprawdzasz przyciski napisać "Call Menu_forward" albo "Call Menu_backward" bo te suby są wołane w celu obsługi menu.

Testuj. W razie problemów pisz :D
przemek6
Posty: 2
Rejestracja: 16 lut 2016, 18:42

Re: Wielopoziomowe menu.

Post autor: przemek6 » 19 lut 2016, 16:47

Cześć :)
Udało mi się posiedzieć trochę nad tym kodem i dzięki Twojemu opisowi prostsze stało się interpretowanie.
Zrobiłem to na pętli warunkowej if i działa :)

Przed pisaniem pierwszego postu, kompilator wywalał mi błąd przy Menu_init itd. Udało się to zrobić.
Nowa wersja LCD Menu tworzy trochę inaczej nazwany plik menu, przez co nie jest w 100% kompatybilna z opisem zamieszczonym na tamtej stronie :)

Dzięki :)
ODPOWIEDZ