Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[Atmega8] [Bascom] Problem z zapętlaniem

flaymen 20 Feb 2009 21:33 1044 6
  • #1
    flaymen
    Level 11  
    witam
    Czy ktoś z wytrawnych bacom-owców mógłby mi podpowiedzieć jak poprawić kod ;)
    Program jest banalny dla was ;) ja dopiero się uczę ;)
    Napisałem program z menu przełączanym jednym klawiszem - zmienna Menu_id zliczana i ze względu na nią i ponowne naciśniecie klawisza wywołuję podprogramy - wszytko działało super dopóki nie dodałem pomiaru temperatury na znanym i lubianym ds18b20. Problem w tym że teraz gdy wyświetlam temp klawisz nie działa - tzn działa ale z dużym opóźnieniem a co więcej zaraz powraca do wyświetlania temp – pomimo tego że zmienna Menu_id odpowiedzialna wydawać by się mogło za wyświetlanie temp ma inna wartość. Rozkładam ręce ;(
    Code:

    $regfile = "m8def.dat"                                      'informuje kompilator o pliku
          'dyrektyw mikrokontrolera
    $crystal = 8000000                                          'informuje kompilator
          'o częstotliwości oscylatora
          'taktującego mikrokontroler

    ' -------------------- temperatura
    Config 1wire = Portc.0
    Deflcdchar 1 , 4 , 10 , 4 , 32 , 32 , 32 , 32 , 32          'znak stopnia

    Dim T1 As Single
    Dim T2 As Single
    Dim B1 As Byte , B2 As Byte , R As Byte
    Dim Tmp As String * 6
    Dim Znak As String * 1
    R = &HFF
    Declare Sub 1wr                                             'podprogram resetujacy magistrale 1w
    '----------------- temperatura

    Config Portc.1 = Output
    Config Portb.2 = Output
    Config Portb.1 = Output
    Config Portd.0 = Output

    Config Pinb.3 = Input                                       'linia PB1 jako wejściowa
    Config Pinb.4 = Input                                       'linia PB2 jako wejściowa
    Config Pinb.5 = Input                                       'linia PB3 jako wejściowa
    Config Lcd = 16 * 2                                         'konfiguracja typu wyświetlacza
          'LCD
    Config Lcdpin = Pin , Db4 = Portd.5 , Db5 = Portd.6 , Db6 = Portd.7 , Db7 = Portd.4 , E = Portd.3 , Rs = Portd.2       'konfiguracja linii
          'mikrokontrolera, do których
          'dołączono wyświetlacz
          'LCD

    Declare Sub Wybierz_menu                                    'procedura wedrujaca po menu
    Declare Sub Dozuj_p1
    Declare Sub Dozuj_p2
    Declare Sub Dozuj_p3


    Dim Menu_id As Byte
    Dim Ilosc_ml_p1 As Byte
    Dim Ilosc_ml_p2 As Byte
    Dim Ilosc_ml_p3 As Byte
    Dim Odliczanie As Byte

    S1 Alias Pinb.3
    S2 Alias Pinb.4
    S3 Alias Pinb.5





    Set Portb.3
    Set Portb.4
    Set Portb.5

    Menu_id = 0

    ' ------------------------------------------ GŁÓWNA PĘTLA -----------------------------------
    Ilosc_ml_p1 = 5
    Ilosc_ml_p2 = 5
    Ilosc_ml_p3 = 5
    Cursor Off
    Menu_id = 0
    Do

      Call Wybierz_menu
      If S3 = 0 Then                                            'jeśli przyciśnięty S3, to
         Waitms 25                                              'opóźnienie dla eliminacji drgań
          'styków
         If S3 = 0 Then
             Incr Menu_id
             Waitms 150
             If Menu_id = 5 Then
                Menu_id = 0
             End If
             Call Wybierz_menu
         End If
      End If


      If Menu_id = 0 Then
           Waitms 25
           Do
            Gosub Temperatura
           'Lcd Znak ; Tmp ; Chr(1)
           Loop Until S3 = 0
      End If

      If Menu_id = 1 Then
         Waitms 25
         Do
           Call Dozuj_p1
         Loop Until S3 = 0
      End If

      If Menu_id = 2 Then
         Waitms 25
         Do
            Call Dozuj_p2
         Loop Until S3 = 0
      End If

     If Menu_id = 3 Then
         Waitms 25
         Do
            Call Dozuj_p3
         Loop Until S3 = 0
      End If

      If Menu_id = 4 Then
         Waitms 25
         Do

         Loop Until S3 = 0
      End If


    Loop
    End                                                         'koniec programu
    ' ------------------------------------------ KONIEC GŁÓWNA PĘTLA -----------------------------------







    Sub Wybierz_menu
        Cls
        Select Case Menu_id
           Case 0 : Lcd " Dozownik v 1.0 "
           'Lowerline
           Case 1 : Lcd "Dozuj P1"
           Case 2 : Lcd "Dozuj P2"
           Case 3 : Lcd "Dozuj P3"
           Case 4 : Lcd "Dozownik auto"
        End Select
    Return
    End Sub



    Sub Dozuj_p1
        Dim Ile_p1 As Byte
        Dim S_p1 As String * 2
        Waitms 25
        Lowerline
        S_p1 = Str(ilosc_ml_p1)
        Lcd Format(s_p1 , "00") ; " ml"

        If S1 = 0 Then
          Waitms 25
          If S1 = 0 Then
              Cls
              Lcd "Dozuj P1"
              Incr Ilosc_ml_p1
              Waitms 25
              Lowerline
              S_p1 = Str(ilosc_ml_p1)
              Lcd Format(s_p1 , "00") ; " ml"
              If Ilosc_ml_p1 = 41 Then
                  Ilosc_ml_p1 = 1
              End If
          End If
        End If
        If S2 = 0 Then
              Waitms 25
              If S2 = 0 Then
                    Portb.1 = 1
                    Ile_p1 = Ilosc_ml_p1
                    For Odliczanie = 0 To Ilosc_ml_p1
                      Cls
                      Lcd "Dozuj P1"
                      Lowerline
                      S_p1 = Str(ile_p1)
                      Lcd Format(s_p1 , "00") ; " ml"
                      Wait 1
                      Decr Ile_p1
                    Next Odliczanie
                    Portb.1 = 0
              End If
        End If
    End Sub

    Sub Dozuj_p2
        Dim Ile_p2 As Byte
        Dim S_p2 As String * 2
        Waitms 25
        Lowerline
        S_p2 = Str(ilosc_ml_p2)
        Lcd Format(s_p2 , "00") ; " ml"

        If S1 = 0 Then
          Waitms 25
          If S1 = 0 Then
              Cls
              Lcd "Dozuj P2"
              Incr Ilosc_ml_p2
              Waitms 25
              Lowerline
              S_p2 = Str(ilosc_ml_p2)
              Lcd Format(s_p2 , "00") ; " ml"
              If Ilosc_ml_p2 = 41 Then
                  Ilosc_ml_p2 = 1
              End If
          End If
        End If
        If S2 = 0 Then
              Waitms 25
              If S2 = 0 Then
                    Portb.2 = 1
                    Ile_p2 = Ilosc_ml_p2
                    For Odliczanie = 0 To Ilosc_ml_p2
                      Cls
                      Lcd "Dozuj P2"
                      Lowerline
                      S_p2 = Str(ile_p2)
                      Lcd Format(s_p2 , "00") ; " ml"
                      Wait 1
                      Decr Ile_p2
                    Next Odliczanie
                    Portb.2 = 0
              End If
        End If
    End Sub

    Sub Dozuj_p3
        Dim Ile_p3 As Byte
        Dim S_p3 As String * 2
        Waitms 25
        Lowerline
        S_p3 = Str(ilosc_ml_p3)
        Lcd Format(s_p3 , "00") ; " ml"

        If S1 = 0 Then
          Waitms 25
          If S1 = 0 Then
              Cls
              Lcd "Dozuj P3"
              Incr Ilosc_ml_p3
              Waitms 25
              Lowerline
              S_p3 = Str(ilosc_ml_p3)
              Lcd Format(s_p3 , "00") ; " ml"
              If Ilosc_ml_p3 = 41 Then
                  Ilosc_ml_p3 = 1
              End If
          End If
        End If
        If S2 = 0 Then
              Waitms 25
              If S2 = 0 Then
                    Portd.0 = 1
                    Ile_p3 = Ilosc_ml_p3
                    For Odliczanie = 0 To Ilosc_ml_p3
                      Cls
                      Lcd "Dozuj P3"
                      Lowerline
                      S_p3 = Str(ile_p3)
                      Lcd Format(s_p3 , "00") ; " ml"
                      Wait 1
                      Decr Ile_p3
                    Next Odliczanie
                    Portd.0 = 0
                    Menu_id = 4
              End If
        End If
    End Sub


    'xxxxxxxxxxxxxx      pomiar temperatury   xxxxxxxxxxxxxxxxxxxxxxxxxx

    Temperatura:


       1wreset                                                     '1wr
       1wwrite &HCC                                                'skip ROM
       1wwrite &H44                                                'convert T
       Waitms 250
       Waitms 250
       1wreset                                                     '1wr
       1wwrite &HCC                                                'skip ROM
       1wwrite &HBE                                                'read

       B1 = 1wread()                                               'czytam czojnik
       B2 = 1wread()

       1wreset                                                     '1wr

       If B2 >= 248 Then                                           'jesli ujemna
       B1 = R - B1                                                 '255 - B1
       B2 = R - B2                                                 '255 - B2
       Znak = "-"
       Else
       Znak = "+"
       End If
       T1 = B1 / 16                                                'w pawo o 4 bajty
       T2 = B2 * 16                                                'w lewo o 4 bajty
       T1 = T1 + T2

       Tmp = Fusing(t1 , " ###.&")

       Cls

       Lcd Znak ; Tmp ; Chr(1)

       Waitms 250
       Waitms 250
       Waitms 250
       Waitms 50

    Return


    [/code]
  • #2
    wader_669
    Level 28  
    1 blad w subie uzyles return.
    Ogolnie jest maslo maslane, malo logicznie myslisz. Po co sprawdzasz 2 rezy menu_id w jednej petli mogles to zrobic raz. Ogolnie duzo bledow jak bedzie mi sie bardzo nudzic to postaram ci sie to poprawic.

    Dodano po 1 [godziny] 13 [minuty]:

    nie ogolnie nie mam ochoty tego poprawiac bo jest mega syf.
    Zmien temperatura na suba.
    Odpal helpa i sprawdz jak wyglada deklaracja zmiennej lokalnej bo masz to zle
    i wywal prawie wszystkie waity totalnie nie wiem po co one

    Dodano po 4 [minuty]:

    wydaje mi sie ze pisales to troche na odwal i wstawiles na elektrodze by ktos ci to sprawdzil, powod dlaczego tak mysle: co chwile mylisz zmienne

    Dodano po 1 [minuty]:

    i nastepnym razem powiedz co ma kod robic a nie ze sie domyslam o co chodzi
  • #3
    atom1477
    Level 43  
    flaymen wrote:

    Program jest banalny dla was ;) ja dopiero się uczę ;)


    Żaden program nie jest dla nikogo banalny jak jest w nim narozp*******ne.


    Nawet jak zamienisz Return na End Sub to program nie będzie działał bo tak go napisałeś że dla Menu_Id =0 program zawsze będzie wracał do wyświetlania temperatur.

    Dodano po 2 [minuty]:

    Pomiędzy "convert T" a "read" to Waitms 750 co najmniej musi być.
    Tego Waitms-a nie usuwaj.
  • #4
    flaymen
    Level 11  
    witam dzieki za odpowiedzi ;)

    tak to prawda ze zaden program nie jest banalny jak nie ma w nim ladu skladu - wybaczcie ale to pierwsze kroki z bacomem - chcialem napisac oprg ktore:
    1. wyswietla temperature
    2. po nacisnieciu mojego s3 czyli zianie stanu Pinb.5 przejdzie do suba gdzie po nacisnieciu s1 czyli Pinb.3 zmienie ilosc ml zmienna Ilosc_ml_p1 nastepnie po zmianie stanu S3 czyli Pinb.5 załacze Portb.1 na Ilosc_ml_p1 * 1s
    3. kolejne naciśniećie s3 (Pinb.5) przechodze do kolejnego suba gdzie odbywa sie to samo tyle ze dla Portb.2 = 1 a w nastepnym subie Portd.0 = 1
    4. kolejna zmiana s3 (Pinb.5) powinna przejsc do wywietlana temperatury

    No i szczerze powiem ze wydawalo mi sie ze tak to wlansie napisalem. Fakt teraz widze ze szereg waitms-ow nie jest potrzeba wiec je wyrzucilem.
    Piszecie:
    Quote:
    Nawet jak zamienisz Return na End Sub to program nie będzie działał bo tak go napisałeś że dla Menu_Id =0 program zawsze będzie wracał do wyświetlania temperatur.


    kurcze wydaje mi sie ze kod:
    Code:
    Menu_id = 0
    

    Do
      Call Wybierz_menu
      If S3 = 0 Then                                            'jeśli przyciśnięty S3, to
         Waitms 25                                              'opóźnienie dla eliminacji drgań
          'styków
         If S3 = 0 Then
             Incr Menu_id
             If Menu_id = 5 Then
                Menu_id = 0
             End If
             Call Wybierz_menu
         End If
      End If


      If Menu_id = 0 Then
          Do
            Call Temperatura
           'Lcd Znak ; Tmp ; Chr(1)
           Loop Until S3 = 0
      End If

      If Menu_id = 1 Then
         Do
           Call Dozuj_p1
         Loop Until S3 = 0
      End If

      If Menu_id = 2 Then
        Do
            Call Dozuj_p2
         Loop Until S3 = 0
      End If

     If Menu_id = 3 Then
         Do
            Call Dozuj_p3
         Loop Until S3 = 0
      End If

      If Menu_id = 4 Then
         Do

         Loop Until S3 = 0
      End If
    Loop
    End       

    działa właśnie tak jak założyłem. Ja rozumiem to tak menu_id = 0 przed petla wiec dla 1 uruchomemia
    pozniej sprawdzam czy nascisniety s3 - jesli tak to zwiekszam menu_id
    pozniej sprawdzam jakie jest to menu_id i wywoluje kolejnego suba - zerowanie menu_id - czyli powrot do temperatury jest dopiero przy piatymnacisnieciu s3 i zmianie menu_id na 0.
    Niestety zmienilem na sekcje temperatury na SUB i niestety nie działa jak należy.
  • #5
    piotr5000
    Level 21  
    Zauważ że S3 słuzy do wyjścia z pętli
    " Loop Until S3 = 0"
    i zmiany Menu_id
    " If S3 = 0 Then
    Incr Menu_id"
    W procedurze temperatura, odczyt z DS18b20 trwa około
    1 sekundy dlatego występuje brak reakcji na klawisz
    jeżeli przycisk przytrzymasz dłużej to czy procesor nie wykona dalszej części programu i wróci do pomiaru temperatury?
    spróbuj zmienić " Loop Until S3 = 0"
    na " Loop Until S2 = 0" w pętli głównej programu

    pozwoli to na jednoznaczne rozróżnienie wyjścia z pętli
    i wejścia w następne menu
  • #6
    flaymen
    Level 11  
    piotr5000 - dzięki za info niestety nie pomoglo ;( przytrzymanie klawisza wprawdzie przelacza menu ale zaraz powraca do wyswietlania temp - i dzieje sie tak bez znaczenia czy
    Code:
    Loop Until S3 = 0
    czy
    Code:
    Loop Until S2 = 0
    powoli zaczynam tracic werwe ;( - nic to szukam i kombinuje dalej - dzieki za checi - nie mniej jednak jesli ma ktos na to sily bardzo prosze o pomoc

    pozdrawiam

    Dodano po 1 [godziny] 5 [minuty]:

    flaymen wrote:
    piotr5000 - dzięki za info niestety nie pomoglo ;( przytrzymanie klawisza wprawdzie przelacza menu ale zaraz powraca do wyswietlania temp - i dzieje sie tak bez znaczenia czy
    Code:
    Loop Until S3 = 0
    czy
    Code:
    Loop Until S2 = 0
    powoli zaczynam tracic werwe ;( - nic to szukam i kombinuje dalej - dzieki za checi - nie mniej jednak jesli ma ktos na to sily bardzo prosze o pomoc

    pozdrawiam


    dziwna sprawa - jako ze programik z temp. zrobil sie za duzy do wersji demo 1.11.9.1 kompilowalalem go na 8 jakiez bylo moje zdziwienie gdy nawet program bez tmep nie dzialal prawidlowo - kopilujac go 9 dzila poprawnie - zdobylem 1.11.9.0 skompilowalem - wgralem i wszytko dzila jak tego chialem - jak narazie SUKCES

    dzieki bardzo za szczere checi pomocy

    pozdrawiam
  • #7
    piotr5000
    Level 21  
    kompilowałem w wersji 1.11.8.7
    w symulacji było OK
    i dlatego pomysł ze zmianą S3 na S2

    pozdrawiam