Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
NOVATEK-ELECTRO POLSKA SP. Z O.O.NOVATEK-ELECTRO POLSKA SP. Z O.O.
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Atmega8 problem z timerem[C] -

28 Jul 2015 23:19 1116 9
  • Level 2  
    Witam
    to mój pierwszy post na tym forum, stąd możecie mi wierzyć jak bardzo jestem zrozpaczony:) jeśli temat jest w złym miejscu to prosiłym moderatora o przeniesiegnie i z góry przepraszam:) zwykle staram się rozwiazywać wszystkie problemy sam ale tym razem mam coś czego nie jestem w stanie zrozumieć.

    Pracuję chwilę nad programem którego działanie polega na tym że liczy czas stanu wysokiego i zależności od czasu trwania generuje impuls po odpowiednim upływie czasu od zbocza opadającego.

    Program w moim odczuciu uważam prawie za gotowy gdyby nie to że po kilku nieprzespanych nocach i wielu nieudanych próbach doszedłem do wniosku że timer źle zlicza mi ilość impulsów/czas trwania stanu wysokiego.
    W oparciu o drugą atmegę mam zrobiony generator PWM z dobraną odpowiednio długością stanu wysokiego. I mimo iż nawet na oscyloskopie impuls mieścił się w poprawnych granicach czasu to według programu przyjmuje on wartość większą niż występująca w ostatnim warunku sprawdzajacego długość czasu stanu wysokiego. >140000us. Komenatrz z wartością "//o=12000" i "//dalrade=1;" służyły jedynie do potwierdzenia moich wątpliwości.

    Prosiłbym was o udzielenie komentarza co może być przyczyną takiego niepoprawnego zliczania czasu?
    Atmega pracuje z czestotliwością 8MHz, Timer ma ustawiony prescaler na 8, 1clk=1us dla timera, fusebity: hFuse D9, lFuse E4.

    [/code]
    Code: c
    Log in, to see the code


    Dodatkowo mam jeszcze jedno pytanie.
    Mianowicie czy jeśli zadeklarujemy sei(); to czy na końcu przerwań musimy dodawać reti(); ? Podczas ich dokładania układ nie generował mi interesującego mnie impulsu. Natomiat w takiej wersji jak jest(czyli bez reti) z kometarzami z ostatniego warunku pomiaru czasu je generował.

    Z góry dziękuje za wszelkie odpowiedzi i sugestię co może być nie tak.
    Pozdrawiam.
  • NOVATEK-ELECTRO POLSKA SP. Z O.O.NOVATEK-ELECTRO POLSKA SP. Z O.O.
  • Moderator on vacation ...
    Witamy na forum, a miejsce na swój temat znalazłeś właściwe :)

    1. Zignorowałeś warning:
    Quote:
    Warning 2 #warning "F_CPU not defined for <util/delay.h>" ...

    a to często prowadzi do problemów: http://mikrokontrolery.blogspot.com/2011/04/bledy-kompilacji-programu.html

    a w tym przypadku chodzi o to, by nie definiować F_CPU w kodzie programu z tych powodów: http://mikrokontrolery.blogspot.com/2011/03/fcpu-gcc-gdzie-definiowac.html


    2. Załączaj tylko io.h i dla porządku jako pierwszy


    3. Kompilator gcc dodaje reti automatycznie o czym możesz przekonać się podglądając plik lss:

    dla:
    Code: c
    Log in, to see the code

    otrzymujesz:
    Code: avrasm
    Log in, to see the code


    Jeśli wstawisz reti bez ściągnięcia ze stosu umieszczonych tam rejestrów to ... program się wysypie::)

    dla:
    Code: c
    Log in, to see the code

    otrzymujesz:
    Code: avrasm
    Log in, to see the code

    bo stos się przepełni.


    4. Stosuj przesunięcia bitowe i predefiniowane etykiety bo łatwiej jest kod analizoawć

    Code: c
    Log in, to see the code



    5. cli(); w przerwaniu nie ma sensu bo flaga ta jest automtycznie wyłączana gdy mikrokontroler wchodzi w funkcję przerwania.


    6. Zmienne opóźnienia

    Code: c
    Log in, to see the code

    niestety: http://mikrokontrolery.blogspot.com/2011/04/gcc-avr-funkcje-opoznienia-delay.html
    bo:

    Quote:
    __builtin_avr_delay_cycles expects a compile time integer constant


    7. Trudno analizować program, który nie ma prawidłowo realizowanych wcięć - możesz to poprawić, czy to problem wklejania go na forum?
  • Level 28  
    Zacząłbym od tego:
    mazur9393 wrote:
    Code: c
    Log in, to see the code

    powinno być raczej coś w stylu:
    Code: c
    Log in, to see the code

    Nie sprawdzałem dokładnie, więc być może to nie jedyny błąd.

    EDIT:
    No i dodam po raz kolejny: opóźnienia generowane przez funkcje z "delay.h" przy włączonych przerwaniach mogą być bardzo niedokładne.
  • NOVATEK-ELECTRO POLSKA SP. Z O.O.NOVATEK-ELECTRO POLSKA SP. Z O.O.
  • Level 2  
    Może nie zignorowałem tylko programuję w Programmers Notepad stąd pewnych nieścisłości kompilator mi nie pokazuje:)

    co do kwestii:
    1. Zamieściłem teraz u góry F_CPU
    2. Załączaj tylko io.h? chodzi o to żeby załaczać jedynie ten plik zamiat include <avr/iom8.h>?
    3. Nie za bardzo znam się na assemblerze ale dzięki za odpowiedz:)
    4. Przy takim ustawianiu rejestrów pozostałe mają wartości domyślne? Staram się raczej zapisywać rejestry heksadecymalnie bo mentalnie mam pewność jak są ustawione bity. Korzystam z tej strony i dosyć dobrze mi w ten sposób zapisywać także proszę o wyrozumienie :)

    http://impuls.elektroda.eu/joomla/index.php?o...ent&view=article&id=78&Itemid=123

    5. To było celem prób dodane czy się poprawi kod. Na chwilę obecną usunąłem ze swojego programu.
    6. Na chwile obecną zmieniłem na komentarz.
    7. Edytowałem kod z 1 postu, mam nadzieję że teraz jest nieco lepiej widoczny:)

    Co do kolegi Andrzeja warunki z obługi przewania timera działają bo za zmienną obliczoną podstawia mi 1:) co do opóźnień z fukcji delay to na chwilę obecną ich dokłaność nie jest dla mnie najistotniejsza ale będę pamietał:)

    Próbowałem działanie programu po tych pewnych drobnych poprawkach i niestety nadal jakoś odnoszę wrażenie że liczba us jakie mierzy timer jest za duża w stosunku do przedziału wartości jakie sobie założyłem.

    Poniżej dorzucam zdjęcia z układu przy działaniu czasu krótszym niż zamierzony i przebiegów oscyloskopu przy podziałce 10ms/działkę. Górny wykres to opóźnienie wzgledem zbocza opadającego, natomiast dolny to czas stanu wyoskiego. Wynika z tego jakoby to wymuszenie dało odpowiednią ilość impulsów aby zmienna counts mieściła się w zakresie ktoregoś warunków z pętli głównej, mimo iż na oscyloskopie wizualnie wygląda jakoby miał ono ~2ms.

    Atmega8 problem z timerem[C] - Atmega8 problem z timerem[C] - Atmega8 problem z timerem[C] -
  • Level 28  
    mazur9393 wrote:
    Co do kolegi Andrzeja warunki z obługi przewania timera działają bo za zmienną obliczoną podstawia mi 1

    mazur9393 wrote:
    Code: c
    Log in, to see the code

    W pliku "iom8.h"
    Code: c
    Log in, to see the code

    W efekcie ICP=0. Zawsze równa się 0. Zawsze będziesz miał spelniony tylko warunek:
    mazur9393 wrote:
    Code: c
    Log in, to see the code

    Warunek if (ICP==1) nie będzie spełniony nigdy.

    Może źle się wyraziłem w poprzednim poście. To nie jest "raczej" źle, to jest na pewno źle.
  • VIP Meritorious for electroda.pl
    1. U góry, tzn gdzie? To musisz zdefiniować w opcjach kompilacji/projektu
    2. Załączając plik avr/io.h mamy pewność, że kompilator dołączy wszystkie pliki z definicjami rejestrów - nie dla wszystkich procesorów znajdziesz jeden plik z definicjami - w skrajnych przypadkach plik będzie niekompletny

    4. Oducz się tego jak najszybciej - praktycznie jak wrócisz do programu po tygodniu będziesz 30 minut analizował co robi dana linijka. A ja na pewno chcąc pomóc nie zamierzam tego przeliczać i analizować numerki bitów. Dalej - korzystaj zawsze z oryginalnej dokumentacji - w tłumaczeniach czasem są mniej lub bardziej istotne błędy.

    7. Nie edytuj programu w pierwszym poście - wpisz go w nowym poście jeszcze raz, bo potem dyskusja będzie bezcelowa jak ktoś to przeczyta - np.
    Quote:
    mówią o ICP==0, a tymczasem dlaczego? Tego nie ma w oryginalnym programie!!!
    To możesz potraktować jako polecenie moderatora ;)
  • Level 2  
    dziękuję wszystkim za zainteresowanie, a szczególnie koledze Andrzejowi za naprowadzenie na trop:D
    zmieniłem:
    Code: c
    Log in, to see the code


    oraz
    Code: c
    Log in, to see the code

    teraz działa:) dzięki wielkie wszystkim jeszcze raz:)
  • Moderator on vacation ...
    mazur9393 wrote:
    Może nie zignorowałem tylko programuję w Programmers Notepad stąd pewnych nieścisłości kompilator mi nie pokazuje:)

    Na pewno pokazuje. A dlaczego ie piszesz w oryginalnym Atmel Studio?

    mazur9393 wrote:
    1. Zamieściłem teraz u góry F_CPU

    To nic nie da - czytałeś wskazany artykuł?
    Zmień środowisko na oryginalne Atmel Studio: http://mikrokontrolery.blogspot.com/2011/04/atmel-studio-spis-tresci.html

    mazur9393 wrote:
    2. Załączaj tylko io.h? chodzi o to żeby załaczać jedynie ten plik zamiat include <avr/iom8.h>?

    Tak ponieważ to on decyduje i załącza właściwy plik (iom8.h, iom32.h, itd.) zależnie od wybranego mikrokontrolera:

    Plik io.h:
    Code: c
    Log in, to see the code


    mazur9393 wrote:
    3. Nie za bardzo znam się na assemblerze ale dzięki za odpowiedz:)

    Na pewno zauważyłeś co napisałem w tym przypadku, czyli że wstawienie reti powoduje że część programu się nie wykona - skutki opisałem.


    mazur9393 wrote:
    4. Przy takim ustawianiu rejestrów pozostałe mają wartości domyślne? Staram się raczej zapisywać rejestry heksadecymalnie bo mentalnie mam pewność jak są ustawione bity. Korzystam z tej strony i dosyć dobrze mi w ten sposób zapisywać także proszę o wyrozumienie :)

    Rozumiemy, tym bardziej że ... dawno, dawno temu w odległej galaktyce ... także tak pisaliśmy, ale wtedy nie było odpowiednich narzędzi. Teraz są i znacząco ułatwiają pisania i analizowanie programu i jak wspomniał piotrva także Tobie będzie łatwiej analizować własny program, po czasie lub gdy będzie sporych rozmiarów.

    mazur9393 wrote:

    Tego typu strony, które zamiast fragmentów dokumentacji w formie graficznej prezentują je w formie tabelek, niestety często zawierają błędy w trakcie ich tworzenia, a każdy bit jest istotny. Zawsze korzystaj z dokumentacji mikrokontrolera, a ze strony jedynie jako elementu pomocniczego w tym wypadku w języku polskim.
  • Level 2  
    Witam po chwili nieobecności:)

    co to pytań i odpowiedzi:
    do kolegi "piotrva":
    1. F_CPU zadeklarowałem na samej górze programu o to mi chodziło :D
    2. Zapamietam na przyszłość:)
    4.Myślę że to kwestia już bardziej kwestia indywidualna jak komu jest wygodniej, mi w zapisie heksadecymalnym posługiwanie się idzie całkiem sprawnie. Ale będę pamietał o tym na przyszłość, że dla innych może być to powodem niechęci do analizy kodu:) co do załączonej strony to na chwilę obecną dosyć dużo mi pomogła i jest szybka w analizowaniu i myślę że jej twórca dosyć starannie przyłożył się do tłumaczenia oryignalnej dokumentacji:) nikomu na siłę nie każę z niej korzystać jedynie polecam:)
    7.Takie rzeczy są dla mnie wiadome:) i jedynie edytowałem wcięcia dla lepszej analizy kodu:)

    do kolegi "dondu":
    Zwykłem używać rzeczy do któych nabyłem zaufanie:) pozatym realizuję raczej dosyć proste programy na chwilę obecną więc w zupełności mi wystarcza:)

    -Co do kwestii kompilatora to nie pokazywał mi błędów. Nie wiem dlaczego. Szybkość taktowania zegara musze definiować dodatkowo w makefile. Jeśli w programie nie wpisze wartości F_CPU błedów nie mi pokazuje(Programmers Notepad).

    -Co do kwestii pliku io.h będę pamietał:)

    -Co do reti(); skutki zrozumiałem, poprostu ciekawiło mnie czemu tak jest:)

    -Jeszcze co do kwestii wpisywania zmiennych w funkcje _delay_ms,_delay_us
    w programmers notepad nie ma z tym problemu, nie wyrzuca mi błedów aczkowiek samo skorzystanie u mnie z tej metody i dodanie linijki "_delay_us(reszta)" zwiększylo zawartość kodu po kompilacji o 5%. Jednak przy późniejszej analizie na oscyloskopie wygląda dosyć wszystko przyzwoicie, nie ma widzialnego pływania odstępu miedzy zboczem opadajacym a impulsem. Natomiast wchodząc w pierwszy warunek zakresowy pętli głównej:

    Code: c
    Log in, to see the code



    Odstęp miedzy zboczami wywołany jest jedynie już fukcją _delay_us(reszta). Co do oscyloskopu który używam nie jest on niestety z pamiecią i nie jest najmłodszy (Tektronix 2225) ale da się zauważyć wtedy minimalne przesuniecie wywoływane właśnie przez tą funkcję i wynika jakoby działała ona poprawnie.



    Mam jeszcze jedno pytanie co do was Panowie.

    Mianowicie jeśli chodzi o nieskończoną pętle w głównej funkcji programu to z jaką częstotliwością ona pracuje?

    Sądziłem że z 8-krotnie częstsza niż timer jeden. Prescaler dla niego ustawiałem na 8. Jednak gdy zwiększam zmienną "o" 8 krotnie na oscyloskopie wynika wtedy że odstęp miedzy zboczem opadajacym a impulsem nie jest poprawny.
    Stąd zmienną "o" zostawiam taką jaka jest bez 8-krotnego zwiększania. Program działa mi wtedy poprawnie jednak bardzo byłbym wdzięczny jeśli ktoś mógłbym mi wytłumaczyc tą kwestię.

    Pozdrawiam
  • Moderator on vacation ...
    mazur9393 wrote:
    1. F_CPU zadeklarowałem na samej górze programu o to mi chodziło :D

    Problem leży w tym, że dostajesz podpowiedź i nie korzystasz z niej.
    Przeczytaj jeszcze raz punkt nr 1 z mojego pierwszego postu - zmień środowisko.

    mazur9393 wrote:
    4.... Ale będę pamietał o tym na przyszłość, że dla innych może być to powodem niechęci do analizy kodu:)

    Uparty jesteś i nie trafia do Ciebie argument, że nie chodzi tylko o nas, ale przede wszystkim o Twoją wygodę przy analizie własnego programu po pewnym czasie. No cóż każdy z nas kiedyś na złość mamie nie nosił czapki, a teraz żałuje chorując na zatoki :)


    mazur9393 wrote:
    Zwykłem używać rzeczy do któych nabyłem zaufanie:) pozatym realizuję raczej dosyć proste programy na chwilę obecną więc w zupełności mi wystarcza:)

    -Co do kwestii kompilatora to nie pokazywał mi błędów. Nie wiem dlaczego.

    Zmień środowisko.


    mazur9393 wrote:
    Szybkość taktowania zegara musze definiować dodatkowo w makefile. Jeśli w programie nie wpisze wartości F_CPU błedów nie mi pokazuje(Programmers Notepad).

    Zmień środowisko i zapomnij o makefile.


    mazur9393 wrote:
    Jeszcze co do kwestii wpisywania zmiennych w funkcje _delay_ms,_delay_us ...

    Jaką wersję tollchain posiadasz? ... zmień środowisko.


    mazur9393 wrote:
    Mianowicie jeśli chodzi o nieskończoną pętle w głównej funkcji programu to z jaką częstotliwością ona pracuje?

    Sądziłem że z 8-krotnie częstsza niż timer jeden. Prescaler dla niego ustawiałem na 8. Jednak gdy zwiększam zmienną "o" 8 krotnie na oscyloskopie wynika wtedy że odstęp miedzy zboczem opadajacym a impulsem nie jest poprawny.
    Stąd zmienną "o" zostawiam taką jaka jest bez 8-krotnego zwiększania. Program działa mi wtedy poprawnie jednak bardzo byłbym wdzięczny jeśli ktoś mógłbym mi wytłumaczyc tą kwestię.

    Rozkazy w pętli głównej realizowane są zgodnie z ustawionym fusebitami zegarem taktującym mikrokontroler. Timer z preskalerem 8 taktowany jest 8 razy wolniej. Nie można natomiast opierać się na częstotliwości taktowania i uzależniać powiązania czasowe pętli głównej do timera tym bardziej, że w Twoim programie występują przerwania i złożone warunki. Innymi słowy, timer i pętla główna to dwa osobne byty, których nie można czasowo dokładnie zgrać, w takim kontekście jak opisałeś.

    Dlatego aby zależności czasowe były dokładne należy korzystać z przerwań jednego lub kilku timerów w zależności od zadania i wolnych zasobów sprzętowych.