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

[Atmega8][Bascom]Sterownie diodą led przez zmienną.

rafi_xd 11 Lut 2011 18:36 3635 14
REKLAMA
  • #1 9136967
    rafi_xd
    Poziom 11  
    Witam.
    Mam problem z napisaniem programu w Bascomie.

    Chcę, żeby przyciskami S1 i S2, po naciśnięciu przycisku S3 zmieniać zmienną (Praca) typu Byte
    i wyświetlać ją na LCD. Później chcę, żeby dioda (D1) świeciła przez tyle sekund
    ile wynosi zmienna i gasła na sekundę (w pętli nieskończonej).

    Dla wyjaśnienia:
    S1 - Dodanie do zmiennej 1.
    S2 - Odjęcie od zmiennej 1.
    S3 - Dopiero po naciśnięciu i przytrzymaniu tego przycisku można zmieniać zmienną.

    Napisałem taki program:

    $regfile = "m8def.dat"                                      'informacje o procesrze
    
    $crystal = 1000000                                          'częstotliwość oscylatora
    
    Config Portb = Input                                        'linia PB jako wejścia
    Config Portd = Output                                       'linia PD jako wyjścia
    
    Config Lcd = 16 * 2                                         'typ lcd
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5       'konfiguracja lini PC do lcd
    
    S1 Alias Pinb.0                                             'S1 zamiast PINB.0
    S2 Alias Pinb.1                                             'S2 zamiast PINB.1
    S3 Alias Pinb.2                                             'S3 zamiast PINB.2
    D1 Alias Portd.0                                            'D1 zamiat PORTD.0
    
    Dim Praca As Byte                                           'zadekalrowanie zmiennej
    
    Praca = 1                                                   'zmienna Praca wynosi 1
    
    Do
    
          If S3 = 0 Then                                        'jeśli S3 jest naciśnięty, to
          Waitms 25
          If S1 = 0 Then                                        'sprawdza, czy S1 jest naciśnięty,
          Praca = Praca + 1                                     'jeśli tak, to do zmiennej Praca dodaj 1
          Else                                                  'w przeciwny razie
          If S2 = 0 Then                                        'jeśli S2 jest naciśnięty, to
          Praca = Praca - 1                                     'od zmiennej Praca odejmij 1
          End If                                                'koniec komendy If
          End If                                                'Koniec komendy If
          End If                                                'Koniec komendy If
    
    
    Cls                                                         'wyczyść lcd
    Lcd "czas pracy: " ; Praca                                  'wyświetlenie zmiennej Praca po słowach: czas pracy:
    
    D1 = 1                                                      'wyłącz D1
    Wait 1                                                      'poczekaj sekunde
    
    D1 = 0                                                      'włącz D1
    Wait Praca                                                  'odczekaj zmienną Praca (sekundy)
    
    
    Loop
    End                                                         'koniec programu


    Program działa, ale nie tak jak bym chciał.
    Konkretnie chodzi o to, żeby móc zmieniać zmienną bez względu jaka część programu jest obecnie wykonywana. Teraz można ją zmieniać tylko wtedy, gdy
    program dojdzie do momentu komendy If, później trzeba czekać aż uc wykona cały program (zapalenie i zgaszenie diody).

    Jeszcze jeden problem, jak już przycisnę przycisk S3, to zmienna potrafi się samoczynnie zmienić (tak jakby S1 lub S2 same się naciskały). Czy jak podłącze je do VCC,
    zamiast do GND i w programie zmienię stan 0 jako przyciśnięty na 1, to problem zniknie(o ile tak można)?

    Za odpowiedź z góry dziękuję.
    Pozdrawiam.
  • REKLAMA
  • #2 9136997
    piotrva
    VIP Zasłużony dla elektroda
    po pierwsze dodaj podciąganie do linii przycisków
    po drugie poczytaj nieco o timerach to wyeliminujesz wait'y i program będzie działał jak chcesz ;-)
  • #3 9137025
    elektro155
    Poziom 26  
    podciagniecia czyli ustaw stan wysoki na wejściach np. PORTB.2 = 1
  • #4 9137500
    rafi_xd
    Poziom 11  
    piotrva napisał:
    po pierwsze dodaj podciąganie do linii przycisków

    Cytat:
    podciagniecia czyli ustaw stan wysoki na wejściach np. PORTB.2 = 1


    Dzięki, to zadziałało, zmienna już samoczynnie się nie zmienia.

    Cytat:
    po drugie poczytaj nieco o timerach to wyeliminujesz wait'y i program będzie działał jak chcesz :wink:

    A nie można byłoby tego zrobić na wait'ach i dać spokój timerom (czytałem o nich,
    ale nie za bardzo je na razie kumam). Może można by zrobić np. tak: komendy odpowiedzialne za dodawanie i odejmowanie od zmiennej wsadzić do osobnej pętli
    Do...Loop i przechodzić do niej po naciśnięciu przyciska S3, a po puszczeniu S3 kontynuowana jest główna pętla?
  • #5 9137631
    janbernat
    Poziom 38  
    Pomysł jest straszny.
    Poczytaj o timerach.
  • REKLAMA
  • #6 9137717
    rafi_xd
    Poziom 11  
    janbernat napisał:
    Pomysł jest straszny.
    Poczytaj o timerach.

    :D
    No dobra, ale w tym przypadku timer ma zliczać impulsy i ilość tych impulsów dodawać lub odejmować od zmiennej? I czy do tego wystarczy jeden timer, czy dwa (do dodawania jeden i do odejmowania jeden)?
  • #7 9137861
    janbernat
    Poziom 38  
    Ratunku!- jeden timer.
    Są timery sprzętowe w każdym procesorze.
    No i w każdym można zrobić programowe- dużo timerów programowych w jednym timerze sprzętowym.
    Ale zacznij czytać książki- bo w internecie to jest mocno pokawałkowane- jakieś sterowanie w oderwaniu od reszty tego co ma robić procesor.
    Bascom dla początkujących występuje w przyrodzie.
    Bascom-a dla zaawansowanych po polsku nie ma niestety.
    Wait powiniem być zakazany dla początkujących.
    Przez te złe nawyczki kiszą się w pętli niemożności.
    P.S.
    To opisują w przyzwoitych książkach:
    Pracujesz w "restauracji" McDonald i robisz pustą pętlę- wrzuć frytki do gara- wyjmij- nałóż.
    Ale co godzinę dzwoni do ciebie narzeczona- to jest przerwanie od timera.
    I zaczyna się dialog- jeśli mnie weźmiesz do kina- to może...
    A jeśli nie- to nie.
    Ale jeśli mi dasz kwiatki- to może.
    Koniec rozmowy- wracasz do gara.
    A za godzinę- znowu telefon.
  • #8 9138027
    rafi_xd
    Poziom 11  
    No dobra, poczytam, nie będę was już powalał moją obszerną wiedzą na temat bascoma :D , a co do książek, to właśnie z nich próbuje coś wyczytać, ale kiepsko mi to idzie.
  • #9 9138059
    janbernat
    Poziom 38  
    Ja dopiero zaczynasz z Bascomem- to od razu przejdź na C.
    http://atnel.pl/wydawnictwo
    Nie warto się uczyć czegoś od czego wkrótce odejdziesz.
    Chyba z ma to być dorywcze proste programowanie.
    A jeśli nic nie wiesz- "Mikrokontrolery dla początkujących".
  • #10 9138604
    piotrva
    VIP Zasłużony dla elektroda
    Ta książka to najlepsze rozwiązanie;-)
    W tydzień przeszedłem z bascoma na c
  • REKLAMA
  • #11 9139604
    rafi_xd
    Poziom 11  
    Z bascomem zacząłem jakiś miesiąc temu, w C zacznę programować jak jeszcze
    trochę poduczę się bascoma (już zacząłem, to skończę).


    Napisałem taki program:

    Cytat:
    $regfile = "m8def.dat"

    $crystal = 1000000

    Config Portb = Input
    Config Portd = Output

    Config Portb.0 = 1
    Config Portb.1 = 1
    Config Portb.2 = 1

    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5

    Config Timer0 = Timer , Prescale = 64

    S1 Alias Pinb.0
    S2 Alias Pinb.1
    S3 Alias Pinb.2
    D1 Alias Portd.0

    Dim Praca As Byte

    Do
    Stop Timer0

    If S3 = 0 Then
    Waitms 25
    If S1 = 0 Then
    Waitms 25
    Timer0 = Timer0 + 1
    Else
    If S2 = 0 Then
    Waitms 25
    Timer0 = Timer0 - 1

    End If
    End If
    End If

    Praca = Timer0

    Cls
    Lcd "czas pracy: " ; Praca


    Loop
    End


    Ten program ma tylko zliczać naciśnięcia przycisków i dodawać lub odejmować
    od zmiennej. Problem jest taki, że timer automatycznie dodaje do zmiennej, pomimo zastosowania komendy:
    Cytat:
    Stop Timer0

    Jak rozwiązać ten problem?
  • #12 9140183
    piotrva
    VIP Zasłużony dla elektroda
    Matko święta!!
    co ty robisz z tym Timerem?
    Skąd czytałeś do czego służą timery??
  • #13 9140440
    rafi_xd
    Poziom 11  
    Z książek "Programowanie mikrokontrolerów AVR w języku BASCOM"
    i "Mikrokontrolery dla początkujących", ale jak już wyżej pisałem kiepsko idzie mi to
    zrozumieć :cry:. Mógłby mi ktoś może napisać, jak mniej więcej miałoby to wyglądać (nie chodzi mi o to, żeby ktoś napisał mi cały program, bo to nie o to chodzi)?
  • REKLAMA
  • Pomocny post
    #14 9158481
    SylwekK
    Poziom 32  
    Jak nie radzisz sobie na razie z tym timerem to przynajmniej nie nadużywaj bezpodstawnie Wait. To co Ci zaproponuję nie zwalnia Cię od ogarnięcia timerów! Ustal sobie jakie dopuszczasz maksymalne opóźnienie pętli i użyj go tylko raz np. 10ms. Za rozwiązanie, może nie do końca eleganckie, zaraz zbiorę burę od fachowców ale w wielu przypadkach to naprawdę wystarczy :)
    Nie podam Ci gotowego przepisu na Twój program tylko zasadę omijania fragmentów programu co czyni je tzw. nieblokującymi:

    Dim Licznik1 As Byte   'wartości 0-255
    Dim Licznik2 As Word   'wartości 0-65535
    
    Licznik1=0   'ustalasz jakąś zmienną, która będzie służyć do zliczania czasu
    Licznik2=0   'w zależności ile niezależnych czasówek będzie potrzeba tworzysz
                     odpowiednią ilość zmiennych
    Do
    Waitms 10   'dopuszczalne opóźnienie pętli głównej
    
    Incr Licznik1
    If licznik1 =150 then   '150x10ms=1500ms czyli 1,5s
    Licznik1=0
    Toggle led1   'zmienia stan pierwszej diody na przeciwny co 1,5s
    End If
    
    Incr Licznik2
    If licznik2 =2500 then   '2500x10ms=25000ms czyli 25s
    Licznik2=0
    Toggle led2   'zmienia stan drugiej diody na przeciwny co 25s
    End If
    
    'dalszy program
    
    Loop
    End


    W powyższym przykładzie masz ograniczoną prędkość wykonywania pętli głównej do 10ms czyli praktycznie tyle może trwać najkrótsze mignięcie diody.
    Zwróć uwagę, że zmiana stanów diod led1 i led2 są zupełnie od siebie niezależne. Jedna zmienia się co 1,5s (bo licznik ustawiony na 150 pomnożony przez opóźnienie pętli 10ms da 1500ms czyli 1,5s), a druga co 25s. Ponadto w dalszej części programów też się coś może wykonywać i jeśli będzie oparte na podobnej zasadzie liczników to też nie wpłynie to znacząco na miganie diod.
    Przeanalizuj dokładnie ten bardzo prosty program.
    Gdyby w tym programie użyć timera wtedy tworzy się liczniki programowe w przerwaniu, które działają zupełnie niezależnie. Polecam temat (drugi post) gdzie kolega mirekk36 właśnie przedstawił takie praktyczne rozwiązanie z zastosowaniem timera.
  • #15 9170811
    rafi_xd
    Poziom 11  
    Witam.
    SylwekK napisał:
    Jak nie radzisz sobie na razie z tym timerem to przynajmniej nie nadużywaj bezpodstawnie Wait. To co Ci zaproponuję nie zwalnia Cię od ogarnięcia timerów! Ustal sobie jakie dopuszczasz maksymalne opóźnienie pętli i użyj go tylko raz np. 10ms. Za rozwiązanie, może nie do końca eleganckie, zaraz zbiorę burę od fachowców ale w wielu przypadkach to naprawdę wystarczy :)
    Nie podam Ci gotowego przepisu na Twój program tylko zasadę omijania fragmentów programu co czyni je tzw. nieblokującymi:

    Dim Licznik1 As Byte   'wartości 0-255
    Dim Licznik2 As Word   'wartości 0-65535
    
    Licznik1=0   'ustalasz jakąś zmienną, która będzie służyć do zliczania czasu
    Licznik2=0   'w zależności ile niezależnych czasówek będzie potrzeba tworzysz
                     odpowiednią ilość zmiennych
    Do
    Waitms 10   'dopuszczalne opóźnienie pętli głównej
    
    Incr Licznik1
    If licznik1 =150 then   '150x10ms=1500ms czyli 1,5s
    Licznik1=0
    Toggle led1   'zmienia stan pierwszej diody na przeciwny co 1,5s
    End If
    
    Incr Licznik2
    If licznik2 =2500 then   '2500x10ms=25000ms czyli 25s
    Licznik2=0
    Toggle led2   'zmienia stan drugiej diody na przeciwny co 25s
    End If
    
    'dalszy program
    
    Loop
    End


    W powyższym przykładzie masz ograniczoną prędkość wykonywania pętli głównej do 10ms czyli praktycznie tyle może trwać najkrótsze mignięcie diody.
    Zwróć uwagę, że zmiana stanów diod led1 i led2 są zupełnie od siebie niezależne. Jedna zmienia się co 1,5s (bo licznik ustawiony na 150 pomnożony przez opóźnienie pętli 10ms da 1500ms czyli 1,5s), a druga co 25s. Ponadto w dalszej części programów też się coś może wykonywać i jeśli będzie oparte na podobnej zasadzie liczników to też nie wpłynie to znacząco na miganie diod.
    Przeanalizuj dokładnie ten bardzo prosty program.
    Gdyby w tym programie użyć timera wtedy tworzy się liczniki programowe w przerwaniu, które działają zupełnie niezależnie. Polecam temat (drugi post) gdzie kolega mirekk36 właśnie przedstawił takie praktyczne rozwiązanie z zastosowaniem timera.


    Dzięki za fatygę i wogóle, a co do timerów, to mniej więcej je kumam.
REKLAMA