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

Realizacja pomiaru czasu AVR gcc

emtezet 11 Lut 2012 20:13 2137 10
REKLAMA
  • #1 10530646
    emtezet
    Poziom 14  
    Witam, próbuję zrobić pomiar czasu między kolejnymi przerwaniami na wejćiu INT0, ten czas ma być później wykorzystany do ustawienia ocr dla timera w trybie CTC.
    Miało to wyglądać tak:
    Uruchamiam timer, gdy na isr(int0_vect) pojawia się impuls ustawiam sobie flage na 1, w funkcji liczącej czas gdy pojawia się flaga przypisuję wartość timera do zmiennej, następnie robię reset. Podczas debugowania jednak okazuje się że to nie działa, przerwanie od T0 działa jak najbardziej niestety zmienna delay się nie zmienia, czy mój schemat rozumowania jest dobry i czy poniższy (skrócony) kod się z tym zgadza:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 10532298
    krru
    Poziom 33  
    Wypadałoby poczekać z obliczaniem, aż to przerwanie na pewno wystąpi.

    cos jak:
    
          while (flaga == 0);
    


    dodane w main pomiędzy uruchom_timer1(); a czas = oblicz_czas();

    Chyba bardziej dokładny wynik otrzymasz, gdy obliczenia od razu uruchomisz w przerwaniu od INT0,
    a zmienna flaga będzie sygnalizować, że wynik już jest.
  • REKLAMA
  • #3 10532402
    mirekk36
    Poziom 42  
    #define TIMER_START  TCCR1B|=(1<<CS12)|(1<<CS10)




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


    I nie potrzeba żadnego przerwania Timera wykorzystywać bo to tylko drastycznie zmniejsza dokładność obliczenia tego czasu. Jak widać wystarczy flaga przerwania z rejestru TIFR
  • #5 10533060
    emtezet
    Poziom 14  
    Czytałem o ICT ale niestety moja płytka jest już wykonana i muszę się posiłkować tym co mam, mój kod już działa, problemem były typy użytych zmiennych, ale fakt borykam się jeszcze z dokładnością.
    Co do rejestru TIFR to co jeżeli występują jeszcze inne przerwania?
    Moj projekt to wyświetlacz widmowy, obliczony czas służy do synchronizacji. Póki co działa to tak ze obliczony czas wysyłam do drugiego timera0 w trybie ctc jako wartość dla OCR0 i w ten sposób odświeżam obraz, w miedzyczasie występują też przerwania z rs232...
    Main to tylko przykład, w rzeczywistości wygląda to tak że w programie po załadowaniu całego obrazu do pamięci wchodzę do funkcji odczytującej jedną klatkę obrazu, która wywoływana jest przez timer ustawiony w tryb CTC i w tej funkcji jest też właśnie obliczanie czasu i wysyłanie go do ocrb.
    Teraz zastanawiam się jak poradzić sobie z błędem dzielenia (jakaś wartość średnia)..bo obraz mimo że ssynchronizowany to na wyższych prędkościach pływa.
  • #6 10533550
    mirekk36
    Poziom 42  
    emtezet napisał:

    Co do rejestru TIFR to co jeżeli występują jeszcze inne przerwania?


    No ale co mają do tego inne przerwania - niech sobie występują ;) nas obchodzi tu tylko flaga od tego przerwania, które ma posłużyć ci do odliczania czasu i już - pokazałem ci jak ją sobie sprawdzać programowo bez odpalania żadnego przerwania. Tylko trzeba pamiętać wtedy o jej kasowaniu przez zapis wartości = 1 jak widać w kodzie.
  • REKLAMA
  • #7 10533901
    emtezet
    Poziom 14  
    Nie do końca rozumiem kiedy mam wywołać ten kod który stworzyłeś, pierwsza sprawa to OCIF1B, nie znalzłem niczego takiego w dokumentacji atmegi, jeżeli chodziło ci o OCIE1B to po wrzuceniu takiego kodu program się resetuje...
  • #8 10533946
    dondu
    Moderator na urlopie...
    Wprawdzie napisałeś, że to skrócona wersja Twojego programu, jednak:

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

    nie zawiera pętli głównej, chyba że jest ona w oblicz_czas(), ale tej funkcji nie załączyłeś.
    Dodatkowo return 0 jest zbędne.

    emtezet napisał:
    ... po wrzuceniu takiego kodu program się resetuje...

    pokaż ten kod ... jak mamy sprawdzić nie widząc go ? :)

    No i podaj co to za mikrokontroler.
  • REKLAMA
  • #9 10534162
    emtezet
    Poziom 14  
    Program jest rozbudowany i złożony z kilku plików żródłowych i nagłówkowych
    ten main był tylko przykładowy.
    Rozchodzi mi się głównie o procedurę liczenia, tak jak radził kolega wrzuciłem ją w procedurę przerwania
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    W mainie jest po prostu zapis danych z portu com i przypisanie funkcji wyświetlającej do gref

    Jedyny problem jaki chciałbym rozwiązać to błąd (tak mi się wydaje) wynikający z dzielenia, który powoduje że mimo wszystko obraz troche pływa...
    uC to atmega16L
  • #10 10534222
    mirekk36
    Poziom 42  
    emtezet napisał:
    Nie do końca rozumiem kiedy mam wywołać ten kod który stworzyłeś, pierwsza sprawa to OCIF1B, nie znalzłem niczego takiego w dokumentacji atmegi, jeżeli chodziło ci o OCIE1B to po wrzuceniu takiego kodu program się resetuje...


    Przecież pokazałem ci tylko przykład na bazie twojego przykładu. To jaką flagę przerwania wykorzystasz i jaki timer sprzętowy to już sprawa drugorzędna. Tymczasem nawet w tej twojej prezentowanej funkcji masz babola bo za pomocą return zwracasz zmienną czas/192 tymczasem ona będzie zawsze = 0 jak widać z ciała tej funkcji.

    Zastanów się więc na spokojnie co ty robisz i jak robisz, bo wszystko a szczególnie twoje przykłady kodu i opisy wyglądają niestety bardzo chaotycznie.

    Jeszcze raz powiem jak to robić:

    1. odpalasz timer za pomocą bitów preskalera CSxx (dowolny timer)
    2. czekasz w pętli nieskończonej while aż zapali się flaga od wybranego przerwania/przepełnienia - musisz ew posłużyć się trybem CTC
    3. wczytujesz po skończeniu pętli zawartość TCNTx i w niej masz swój czas
    4. koniecznie kasujesz flagę tego przerwania

    no ale już czy to nadaje się wprost do przerwania to nie wiem bo niestety nie wiem w ogóle jak działa twój program. To było podane w odniesieniu do pętli głównej bo przecież sam taki przykład podawałeś że potrzebujesz mierzyć ten czas w pętli głównej a ty teraz coś mieszasz i kombinujesz w przerwaniu INTx ;) robi się z tego pomieszanie z poplątaniem trochę :(

    Dodano po 1 [minuty]:

    Poza tym po kiego? dajesz wewnątrz przerwania cli() czy zapisujesz SREG - toż to już jakieś kosmiczne nieporozumienie - przecież to robi za ciebie EPILOG i PROLOG makra przerwania a ty to niepotrzebnie dublujesz.
  • #11 10534263
    emtezet
    Poziom 14  
    cli daję bo wyczytałem w dokumentacji atmegi że powinno się z niego korzystać, dopiero zaczynam zabawę z uC, to co robi program napisałem w poście tuż przed twoim, czytając to co piszesz mój zamysł był właśnie podobny:
    odpalam timer
    w momencie wystąpienia zdarzenia na into zczytuję wartość timera
    resetuję timer
    z przerwania int0 korzystam bo do niego właśnie podłączony jest mój hall,

    póki co to działa, pozostał mi problem tylko z dokładnością.
REKLAMA