logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega16/32][Bascom] Obsługa przycisków w menu

morswin89 06 Mar 2011 14:17 3115 18
REKLAMA
  • #1 9242361
    morswin89
    Poziom 23  
    Witam

    Napisałem coś takiego:

    Do
    If Ok = 0 Then
          Waitms 50
          If Ok = 0 Then
             Sound Buzer , 1 , 100000
             Set Buzer
             Gosub Menu
          End If
       End If
    
    Loop
    End
    
    
    Menu:
    
    Cls
    Menuu = 1
    Do
    Locate 1 , 1
    Select Case Menuu
    
    Case Is = 1
    Lcd "Harmonogram  "
    If Ok = 0 Then
          Waitms 25
          If Ok = 0 Then
             Sound Buzer , 1 , 100000
             Set Buzer
             Gosub Harmonogram
          End If
       End If
    
    Case Is = 2
    Lcd "Dawka reczna "
    If Ok = 0 Then
          Waitms 25
          If Ok = 0 Then
             Sound Buzer , 1 , 100000
             Set Buzer
             Gosub Dawka_reczna
          End If
       End If
    
    Case Is = 3
    Lcd "Kalibracja   "
    If Ok = 0 Then
          Waitms 25
          If Ok = 0 Then
             Sound Buzer , 1 , 100000
             Set Buzer
             Gosub Kalibracja
          End If
       End If
    
    
    Case Is = 4
    Lcd "Zegar        "
    If Ok = 0 Then
       Waitms 25
       If Ok = 0 Then
          Sound Buzer , 1 , 100000
          Set Buzer
          Gosub Ustaw_czas
       End If
    End If
    
    Case Is = 5
    Lcd "Pokaz nastawy"
    If Ok = 0 Then
          Waitms 25
          If Ok = 0 Then
            Sound Buzer , 1 , 100000
            Set Buzer
             Gosub Pokaz_nastawy
          End If
       End If
    
    Case Is = 6
    Lcd "Reset eeprom "
    If Ok = 0 Then
          Waitms 25
          If Ok = 0 Then
             Sound Buzer , 1 , 100000
             Set Buzer
             Gosub Reset_eeprom
          End If
       End If
    End Select
    
    If Up = 0 And Menuu < 6 Then
       Incr Menuu
       Sound Buzer , 1 , 100000
       Set Buzer
       Waitms 300
    End If
    
    If Up = 0 And Menuu = 6 Then
       Menuu = 1
       Sound Buzer , 1 , 100000
       Set Buzer
       Waitms 300
    End If
    
    If Down = 0 And Menuu > 1 Then
       Decr Menuu
       Sound Buzer , 1 , 100000
       Set Buzer
       Waitms 300
    End If
    
    If Down = 0 And Menuu = 1 Then
       Menuu = 6
       Sound Buzer , 1 , 100000
       Set Buzer
       Waitms 300
    End If
    
    Loop Until Esc = 0
       Sound Buzer , 1 , 100000
       Set Buzer
       Waitms 100
    
    Cls
    Return


    Wszytko działa ale gdy przechodzę do jakiegoś podmenu to od nowa muszę sprawdzać przyciski w celu ustawienia jakiejś zmiennej. Da się to jakoś zrobić inaczej aby w kółko nie powtarzać sprawdzania przycisków.
  • REKLAMA
  • #2 9242875
    gray77
    Poziom 12  
    Aby uniknąć duplikowania praktycznie tych samych linijek kodu co kolejną pozycję menu, wystarczy że stworzysz sobie podprogram sprawdzania klawiszy i będziesz się do niego odwoływał wtedy, gdy potrzebujesz. W podprogramie sprawdzasz klawisze, ustawiasz jakąś flagę i po powrocie sprawdzasz tylko wartość tej flagi. Unikasz kilku linijek kodu z IFami no i moim zdaniem program staje się troszkę przejrzystszy.

    Ja tak mam zrobiony sterownik czasowy i wiele mi to ułatwia przeglądanie listingu.
  • REKLAMA
  • Pomocny post
    #4 9243094
    gray77
    Poziom 12  
    Dla sprawdzania jednego klawisza:

    do
    ...
    ...
    ...
    gosub sprawdzanie_klawiszy
    if flaga = 1 then
       instrukcje gdy wciśnięty klawisz
    end if
    ...
    ...
    ...
    loop
    
    
    sprawdzanie_klawiszy:
      flaga = 0
      if Ok = 0 then
          waitms 50
          if Ok = 0 then
              flaga = 1
          end if
      end if
    return


    mniej więcej tak to ma wyglądać.

    Jeśli chcesz sprawdzać kilka klawiszy robisz bardzo podobnie. Rozbudowujesz tylko podprogram sprawdzanie_klawiszy a w programie głównym stosujesz komendę select case.
  • #5 9243961
    morswin89
    Poziom 23  
    Dzięki, mam jeszcze pytanie z innej beczki a mianowicie problem z obsługa przerwania.

    Config Pind.2 = Input
    Config Int0 = Low Level
    On Int0 Przerwanie
    
    A = 0
    F = 0
    
    Enable Interrupts
    Enable Int0
    
    
    Do
    If Ok = 0 Then
          Waitms 50
        If Ok = 0 Then
            Sound Buzer , 1 , 100000
            Set Buzer
             Gosub Menu
          End If
       End If
    
    
    
    If F = 1 Then
    Cls
    Lcd "przerwanie"
    Wait 1
    Cls
    F = 0
    Enable Int0
    End If
    
    Loop
    End
    
    Przerwanie:
    Enable Interrupts
    Incr A
    If A = 20 Then
    A = 0
    F = 1
    Disable Int0
    Return
    Else
    Return
    End If
    


    Wejście INT0 połączone jest z wyjściem INT PCF8583 czyli przerwanie powino występować co sekundę, czyli w tle powinno zliczyć do 20 sekund i dopiero wyświetlić napis ale tak się nie dzieje.
  • REKLAMA
  • #9 9244572
    morswin89
    Poziom 23  
    Sprawdzałem woltomierzem i zmienia się na pewno, jak spróbowałem na prostszym programie to działało tzn. jednokrotne wejście do podprogramu wywołanego przerwaniem a później blokada przerwań. O jakie bity dokładnie Ci chodzi?
  • #10 9244608
    gray77
    Poziom 12  
    Właśnie tak jak kolega xury mówi, podłącz leda pod wyjście INT z PCFa i zobaczysz, czy miga co 1 sekundę.
    Jeśli ci będzie migała, wtedy będziemy się zastanawiać, dlaczego program nie działa należycie.

    I jeszcze jedna, bardziej estetyczna sprawa. Staraj się robić wcięcia w listingach, bo bez nich to można dostać oczopląsu. Naprawdę źle się czyta.

    Edit:
    Ooo, chyba w jednym czasie napisaliśmy posty :)

    Edit:
    Może w podprogramie obsługi przerwań nie używaj ogólnie enable/disable interrups tylko jednostkowo enable/disable INT0.....
  • REKLAMA
  • #13 9244788
    gray77
    Poziom 12  
    morswin89 napisał:
    Wydaje mi się, że w wyniku przerwania resetuje się procesor i program zaczyna się od momentu ekranu powitalnego.


    Wydaje Ci się... ale nie jesteś pewien.
    Na to masz prosty sposób. Dodaj jakiś napis na samym początku programu, przed pętlą Do Loop i potem już będziesz wiedział, czy uC resetuje się i zaczyna prace od nowa czy nie.

    Może faktycznie pomoże to co pisałem w poście wyżej, używaj wł wył przerwania jednostkowo.
  • #14 9244846
    morswin89
    Poziom 23  
    $regfile = "m16def.dat"
    $crystal = 8000000
    
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db7 = Pa.2 , Db6 = Pa.3 , Db5 = Pa.4 , Db4 = Pa.5 , E = Pa.6 , Rs = Pa.7
    
    Config Pind.2 = Input
    Config Int0 = Low Level
    
    Dim F As Byte
    Dim A As Byte
    
    Enable Interrupts
    Enable Int0
    On Int0 Przerwanie
    
    
    Cursor Off
    Cls
    Locate 1 , 1
    Lcd "ekran powitalny"
    
    Wait 3
    Cls
    
    
    
    Do
    Locate 1 , 1
    Lcd "ekran"
    
    If F = 1 Then
    Cls
    Locate 2 , 1
    Lcd "przerwanie"
    Wait 1
    Cls
    F = 0
    Enable Int0
    End If
    
    Loop
    End
    
    
    Przerwanie:
    
    Disable Int0
    Incr A
    If A = 10 Then
    A = 0
    F = 1
    Else
    End If
    
    Enable Int0
    Return


    Jest już prawie dobrze, nie zlicza jeszcze dobrze tych 10 sekund a potem coś wyświetla.
  • #15 9244900
    gray77
    Poziom 12  
    morswin89 napisał:
    Jest już prawie dobrze, nie zlicza jeszcze dobrze tych 10 sekund a potem coś wyświetla.


    Co znaczy nie zlicza dobrze? Co pokazuje na wyświetlaczu?
    Jeśli nie masz przy PCFie kwarcu zegarkowego to zawsze będziesz miał niewielkie rozbieżności w czasie.
  • Pomocny post
    #17 9244977
    gray77
    Poziom 12  
    Wiec tak:
    W ogóle wyrzuciłbym zmienna/flagę F. Nie jest potrzebna tutaj. W programie głównym zamiast sprawdzania F, sprawdzaj A, czyli warunek IF z przerwania przenieś do programu głównego, łącznie z zerowaniem A. W przerwaniu zwiększaj tylko A.

    Zamiast:
    If F = 1 Then
       Cls
       Locate 2 , 1
       Lcd "przerwanie"
       Wait 1
       Cls
       F = 0
       Enable Int0
    End If 


    zrobilbym
    If A >= 10 Then
       Cls
       Locate 2 , 1
       Lcd "przerwanie"
       Wait 1
       Cls
       A = 0
    End If


    I wyrzuć
    Disable Int0 
    z obsługi przerwania. Mierzysz tylko odcinki jednosekundowe przecież, wiec nie musisz wyłączać przerwań.
  • #19 9245084
    gray77
    Poziom 12  
    No i dobrze.Forum jest po to by pomagać. Ja tez jestem początkujący i tez wiele się z elektrody nauczyłem.

    Pozdrawiam i wielu projektów życzę.

    :D
REKLAMA