Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

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

rafi_xd 11 Lut 2011 18:36 3299 14
  • #1 11 Lut 2011 18:36
    rafi_xd
    Poziom 10  

    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:

    Code:
    $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.

    0 14
  • #3 11 Lut 2011 18:47
    elektro155
    Poziom 26  

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

    0
  • #4 11 Lut 2011 20:21
    rafi_xd
    Poziom 10  

    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?

    0
  • #5 11 Lut 2011 20:43
    janbernat
    Poziom 38  

    Pomysł jest straszny.
    Poczytaj o timerach.

    0
  • #6 11 Lut 2011 20:56
    rafi_xd
    Poziom 10  

    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)?

    0
  • #7 11 Lut 2011 21:17
    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.

    0
  • #8 11 Lut 2011 21:50
    rafi_xd
    Poziom 10  

    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.

    0
  • #9 11 Lut 2011 21:58
    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".

    0
  • #11 12 Lut 2011 11:07
    rafi_xd
    Poziom 10  

    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?

    0
  • #13 12 Lut 2011 13:52
    rafi_xd
    Poziom 10  

    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)?

    0
  • Pomocny post
    #14 16 Lut 2011 08:47
    SylwekK
    Poziom 29  

    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:

    Code:
    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.

    0
  • #15 18 Lut 2011 22:23
    rafi_xd
    Poziom 10  

    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:

    Code:
    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.

    0