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 - Timer1 nie odlicza czasu przy kwarcu 16MHz i preskalerze 64

zakochanyy 08 Gru 2014 00:17 1029 7
REKLAMA
  • #1 14201978
    zakochanyy
    Poziom 10  
    Dzień dobry.

    Mam problem z ustawieniem odliczania czasu za pomocą timera w Atmega8. uC taktowane kwarcem 16MHz, preskaler 64, w kalkulatorze otrzymałem wartość 24999 jeżeli pożądane jest 100ms.

    if zaznaczony slashami odpowiada za odczyt ilości zliczonych impulsów i po przekroczeniu zadanej wartości dodać 1/10 sek (zmienna ssek), aż do otrzymania pełnej sekundy.

    Nie mam pojęcia gdzie leży problem, cały dzień się z tym męczę.

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



    Problem leży w kodzie samego zliczania czy w ogóle wywołania timera? Za wszelkie wskazówki oraz pomoc dziękuję.
    Pozdrawiam.
  • REKLAMA
  • Pomocny post
    #2 14202084
    linuxtorpeda
    Poziom 26  
    W jaki sposób objawia się problem? Tak poza tym, to mam kilka uwag:
    1) program nie będzie zbyt dokładnie odmierzał czasu, może gubić całe 100 milisekundowe odcinki czasu,
    2) sekundy, minuty, godziny będą trwać o jedną "mniejszą" jednostkę za krótko, tzn. np. minuta będzie trwać 59 sekund zamiast 60 sekund,
    3) definicję częstotliwości kwarcu powinno się podawać w makefile, nie w pliku źródłowym, jest to mniej problematyczne,
    4) nie "includuje" się plików .c, a jedynie same pliki nagłówkowe - pliki obiektowe powstałe z kompilacji plików .c łączy linker, nie ma więc potrzeby włączania plików .c do kodu źródłowego pliku z definicją funkcji main(),
    5) nie stosuje się zwykle ścieżek bezwzględnych w ścieżkach włączanych plików nagłówkowych,
    6) mam wrażenie, że ekran LCD będzie strasznie migotać i odczytanie czegokolwiek może być niemożliwe.

    W sumie to nie widzę powodu, dla którego timer mógłby nie pracować, ale może czegoś nie zauważam.
  • REKLAMA
  • Pomocny post
    #3 14202100
    wojekkk
    Poziom 18  
    Tak się nie robi. Myślę że ten timer się parę razy przepełni zanim obsłuży LCD.

    Ustaw timer tak aby wywoływał przerwanie przy danej wartości i w tym przerwaniu dodawaj jakąś zmienną o 1 i czyść licznik.
  • REKLAMA
  • #4 14202198
    zakochanyy
    Poziom 10  
    linuxtorpeda
    Błąd pojawia się w tym, że zmienna sek nie zmienia wartości.


    1. Skąd te 100 ms straty?
    2. Poza tym, że doliczanie sekund należy przenieść za drzewo warunków odpowiadających za min godziny wszystko działa ok - zmienne inkrementują na końcach warunków.
    3. Natknąłem się na ten temat, poprawię.
    4. Nie wiedziałem, ok.
    5. Tak mi łatwiej organizować biblioteki, ale chyba w niczym to nie przeszkadza?
    6. Aktualnie miga wszystko co mniej więcej 1s (opóźniam wykonania i dodaję sekundy delayem) jeżeli będzie to przeszkadzać, to nie będę miał problemów ze zmianą tego.

    wojekkk Jak wrócę z pracy to spróbuję w ten sposób coś znaleźć, ale czy przy 16bitowym 24999 nie powinno się mieścić?
  • REKLAMA
  • #5 14203119
    linuxtorpeda
    Poziom 26  
    1) Strata z dokładnie tego powodu, o którym wspomniał wojekkk.
    5) Może przeszkadzać przy publikacji kodu, przenoszeniu na innego kompa, itp.

    Generalnie obsługa timera powinna mieć wyższy priorytet niż reszta programu, bo od niej zależy dokładność. Nie liczyłbym na to, że wykonanie funkcji obsługi LCD za każdym razem wykona się tak, że nie przeszkodzi to odmierzaniu czasu. Tak poza tym nawet i bez LCD powstaną niedokładności w pomiarze czasu spowodowane m.in. różnym czasem trwania poszczególnych gałęzi w instrukcjach warunkowych, przeważnie timer trzeba zerować zaraz po wykryciu przepełnienia, a dopiero później wykonuje się resztę. Najlepiej by było jedynie zainicjalizować TCNT1 i podejmować akcje tylko przy jego przepełnieniu.

    Tak jak napisał kolega wyżej, radziłbym wykorzystanie przerwań.

    Jeśli zmienna sek nie zmienia wartości, spróbuj wyświetlać zawartość TCNT1 i zobacz czy się zmienia, być może sek nie zmienia wartości z innego powodu niż myślisz.
  • #7 14204797
    zakochanyy
    Poziom 10  
    Poszukałem, poczytałem, wypociłem coś takiego:

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


    Niestety co 3 sekunda jest skrócona (wyświetlam ją na LCD) i w tym punkcie utkwiłem.

    //edit:

    Podaję jeszcze cały kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #8 14204884
    dondu
    Moderator na urlopie...
    Zmienna sek powinna być volatile: http://mikrokontrolery.blogspot.com/2011/04/problemy-c-volatile.html

    ssek natomiast zrób statyczną w funkcji przerwania:

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


    Przy okazji warto dbać o niezawodność kodu i stosować zawsze unsigned tam gdzie liczby nie będą ze znakiem. Wprawdzie ani godziny, ani minuty, czy też sekundy nie przekroczą maksymalnych ich wartości, ale porządek warto mieć.

    Poza tym, taktujesz swój mikrokontroler zegarem 16MHz, a w pętli głównej jak szybko się da ciągle wyświetlasz i kasujesz wyświetlacz - po co? Ludzkie oko i mózg potrzebują około 1/4 sekundy, by zobaczyć i zrozumieć co jest na wyświetlaczu.
REKLAMA