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

[ATMEGA8] licznik czasu - prośba o pomoc

Graba1987 31 Mar 2011 21:10 6450 34
  • #1 9346298
    Graba1987
    Poziom 11  
    Witam.
    Mam takie oto zadanie: po wciśnięciu przycisku ma zacząć się odliczanie czasu, po puszczeniu przycisku koniec odliczania. Wartość na bieżąco wyświetlana na LCD

    Z obsługą LCD spokojnie dam sobie radę, ale z timerów i przerwań jeszcze nigdy nie korzystałem.
    Prosiłbym o linka jeśli ktoś widział gdzieś podobny program albo opis konfiguracji timerów i przerwań zewnętrznych lub o jakieś wskazówki.
    Pracuję na WinAVR.
    Pozdrawiam!
  • Pomocny post
    #2 9346327
    dondu
    Moderator na urlopie...
    Na forum timerów jest zapewne sporo - użyj wyszukiwarki.
    Podobnie w sieci.

    Pisząc "odlicznie czasu" masz na myśli zegar czasu rzeczywistego (sek, min, godz), czy jakąś inną jednostkę np. mikrosekundy, itp?

    WinAVR - jeśli możesz zainstaluj AVR Studio 4 i nie męcz się więcej.
  • #3 9346349
    Graba1987
    Poziom 11  
    sekundy z rozdzielczością 0.1
    ma ktoś jakiś link z opisem + przykład do timerów?
    z datasheeta nie ogarniam :(
  • #5 9346424
    Graba1987
    Poziom 11  
    Jak powinna wyglądać konfiguracja timera i przerwania wyzwalanego przyciskiem?
    Kawałek kodu z opisem na pewno by mi bardzo pomógł i sam bym to powklejał :)
  • Pomocny post
    #6 9346443
    dondu
    Moderator na urlopie...
    O nie na gotowca nie licz :)
    Ale jeżeli chcesz to mogę Cię naprowadzać i poprawiać błędy w kodzie.
    To pozwoli Ci nauczyć się czytać i rozumieć datasheet w zakresie timerów i przerwań.

    Pasuje?
  • #7 9346469
    Graba1987
    Poziom 11  
    Jasne.
    To może na początek powiedz którego timera użyć i które rejestry muszę ustawić. Wartości wyczytam sobie z datasheeta ;)
    Mam go skonfigurować tak żeby się przepełniał co 0.1s i wtedy zwiększał zmienną?
  • #9 9346503
    Graba1987
    Poziom 11  
    angielski dobrze, datasheeta pobieżnie.
  • #10 9346514
    dondu
    Moderator na urlopie...
    OK,
    W razie problemów ze zrozumieniem tutaj znajdziesz datasheet po polsku dla ATMEGA16: http://www.pg.gda.pl/~zbczaja/pdf/atmega16mmr.pdf

    Odpowiedzi na twoje 2 pytania:
    1. Proponuję Timer1 + preskaler
    2. Dokładnie tak

    Zobacz w datasheet (angielski dla Atmega8) schemat: Figure 31.
    Znajdziesz tam preskaler i sterjące nim CS10, CS11, CS12.

    Dodano po 4 [minuty]:

    Jaki masz kwarc?

    Dodano po 51 [minuty]:

    Ponieważ uciekłeś spać, to zostawiam Ci podpowiedzi do przeczytania i zrozumienia z datasheet:

    1. znajdź rejestr ustawiający ten preskaler
    2. najprościej będzie wykorzystać tryb CTC timera1, znajdziesz go na str 88 i 89 - przeczytaj.
    3. przeglądnij schematy Figure 33. i Figure 35.
    4. napisz co wiesz o przerwaniach.
  • #11 9348578
    Graba1987
    Poziom 11  
    1. TCCR1B -> CS12:0
    2. TCCR1A -> ustawić bit WGM12

    Kwarc będzie 8MHz
    Wiem czym są przerwania, ale nie wiem jak wyglądają od strony kodu.

    Nie wiem jak napisać kod do:

    - wciśnięcie przycisku uruchamia timer (jak wystartować timer?)
    - TCNT1 uzyskuje wartość równą OCR1A(??) w trybie CTC i uruchamia przerwanie, które dodaje 0.1ms itd itp
    - puszczając przycisk zatrzymujemy działanie timera
    - wyświetlanie zmiennych (sekundy.setne) umieścić w pętli głównej?

    Już powoli ogarniam jak to działa, ale przydały by się jakieś przykłady z drobnym opisem.

    Czy rejestry o których pisałem wyżej wystarczą do uruchomienia timera?

    Dzięki za dotychczasową pomoc :)
  • #12 9348629
    dondu
    Moderator na urlopie...
    Jestem więc możemy dalej lecieć z tematem ... zaraz odpowiem.

    Dodano po 13 [minuty]:

    Jak zwykle będę odpowiadał na raty:

    1. OK
    2. OK

    Twój algorytm, jest jednym z możliwych rozwiązań, i jest jak najbardziej prawidłowy.
    Ale nie napisałeś w nim nic o przerwaniu - uzupełnij go.

    Co do przykładu, to Ci nie potrzebny, bo z moim wsparciem sam zaraz go napiszesz bo jak widzę kojarzysz prawidłowo :)
  • #14 9348699
    dondu
    Moderator na urlopie...
    Oczywiście, ale korzystanie datasheet daje szansę na poradzenie sobie w przypadkach, co do których tutorial nie znajdziesz :)

    Następny krok to strona 89 - wzór na częstotliwość - dasz radę wyliczyć z niego OCRnA (dla Ciebie to będzie OCR1A)?
  • #15 9348723
    Graba1987
    Poziom 11  
    49999 dla kwarcu 8MHz i prescalera 8 :)
    żeby wszystko tak mięciutko szło :D

    częstotliwość żądana 10Hz
  • #16 9348754
    dondu
    Moderator na urlopie...
    Będzie szło jeżeli ze mną wytrzymasz :D
    Tyle że ten wzór dotyczy częstotliwości na wyjściu OCRx (sorki niepotrzebnie Ci to pokazałem).


    Policzmy to tak:

    8MHz / preskaler / 10Hz
    8.000.000 / 256 / 10 = 3125

    Gdybyś użył preskalera 8 to OCR1A musiało = 100.000 ale niestety jest tylko 16bitowe. Stąd trzeba użyć większy preskaler.

    Zacznij pisać program:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Teraz coś o przerwaniach:

    Trzeba włączyć przerwania z Timera1 - znajdź rejestr TIMSK.
    Dodatkowo potrzebna jest funkcja obsługi przerwania ISR() z wektorem przerwań z komparatora .

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Więcej na temat ISR i wektorów znajdziesz tutaj:
    http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html


    Wklejaj swoje wypociny po każdej zmianie (będzie nam łatwiej).
  • #17 9348962
    Graba1987
    Poziom 11  
    Jak dotąd wypociłem tyle ;)

    Kod: C#
    Zaloguj się, aby zobaczyć kod
  • #18 9348963
    dondu
    Moderator na urlopie...
    Sprawdzam ...

    1. sekunda także musi być volatile (bo jest inkrementowana w przerwaniu i używana także w pętli głównej).
    2. skoro nie przewidujesz wartości ujemnych :) to warto by zmienne sekunda i dziesiątka były unsigned

    Konstrukcja dość niebezpieczna:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Chodzi o to, że na bitach WGM10-WGM13 powinieneś mieć binarnie 0100.
    Niestety tak napisanym rozkazem z użyciem |= (czyli OR), ustawiasz jedynie bit WGM12, ale nie zerujesz pozostałych. Stąd jeżeli jakimś cudem będą tam jedynki ustawiony zostanie niewłaściwy tryb.
  • #19 9348983
    Graba1987
    Poziom 11  
    tak?
    Kod: C#
    Zaloguj się, aby zobaczyć kod
  • #21 9349000
    Graba1987
    Poziom 11  
    Sekund może być więcej niż 255, a double jest dla funkcji sprintf (chyba nie ma żadnej funkcji wstawiającej longa).

    Edit: ajjjj pomyliłem zmienne "o 1 stopień długości", oczywiście char i int wystarczą w zupełności

    Czy takie coś zadziała?
    Na pewno jest jakaś bardziej elegancka opcja ;)


    Kod: C#
    Zaloguj się, aby zobaczyć kod
  • #23 9349028
    Graba1987
    Poziom 11  
    czym się różni pierwsza Twoja opcja od mojaj? :P
  • #25 9349047
    Graba1987
    Poziom 11  
    czyli będzie:
    Kod: C#
    Zaloguj się, aby zobaczyć kod


    a jak reszta?
    już dokładam kwarc na stykówce i programuje :)
  • #27 9349141
    Graba1987
    Poziom 11  
    Kod: C#
    Zaloguj się, aby zobaczyć kod


    na lcd wyświetla się tylko literka "a umlaut" :D
  • #29 9349230
    Graba1987
    Poziom 11  
    Zmienną tekst trzeba było zainicjować inaczej i po ustawieniu fusebitów (1s zajmowała 8s) śmiga aż miło:)
    Kod: C#
    Zaloguj się, aby zobaczyć kod
REKLAMA