Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[ATMEGA8] licznik czasu - prośba o pomoc

Graba1987 31 Mar 2011 21:10 6168 34
  • #1
    Graba1987
    Level 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!
  • Helpful post
    #2
    dondu
    Moderator on vacation ...
    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
    Graba1987
    Level 11  
    sekundy z rozdzielczością 0.1
    ma ktoś jakiś link z opisem + przykład do timerów?
    z datasheeta nie ogarniam :(
  • #5
    Graba1987
    Level 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ł :)
  • Helpful post
    #6
    dondu
    Moderator on vacation ...
    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
    Graba1987
    Level 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
    Graba1987
    Level 11  
    angielski dobrze, datasheeta pobieżnie.
  • #10
    dondu
    Moderator on vacation ...
    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
    Graba1987
    Level 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
    dondu
    Moderator on vacation ...
    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
    dondu
    Moderator on vacation ...
    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
    Graba1987
    Level 11  
    49999 dla kwarcu 8MHz i prescalera 8 :)
    żeby wszystko tak mięciutko szło :D

    częstotliwość żądana 10Hz
  • #16
    dondu
    Moderator on vacation ...
    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:

    Code: c
    Log in, to see the code



    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 .

    Code: c
    Log in, to see the code


    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
    Graba1987
    Level 11  
    Jak dotąd wypociłem tyle ;)

    Code: csharp
    Log in, to see the code
  • #18
    dondu
    Moderator on vacation ...
    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:
    Code: c
    Log in, to see the code

    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
    Graba1987
    Level 11  
    tak?
    Code: csharp
    Log in, to see the code
  • #21
    Graba1987
    Level 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 ;)


    Code: csharp
    Log in, to see the code
  • #23
    Graba1987
    Level 11  
    czym się różni pierwsza Twoja opcja od mojaj? :P
  • #25
    Graba1987
    Level 11  
    czyli będzie:
    Code: csharp
    Log in, to see the code


    a jak reszta?
    już dokładam kwarc na stykówce i programuje :)
  • #27
    Graba1987
    Level 11  
    Code: csharp
    Log in, to see the code


    na lcd wyświetla się tylko literka "a umlaut" :D
  • #29
    Graba1987
    Level 11  
    Zmienną tekst trzeba było zainicjować inaczej i po ustawieniu fusebitów (1s zajmowała 8s) śmiga aż miło:)
    Code: csharp
    Log in, to see the code