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

Jak ustawić timer1 żeby przerwanie występowało co 1us?

antoniv10 13 Kwi 2021 00:05 816 11
REKLAMA
  • #1 19376260
    antoniv10
    Poziom 3  
    Witam, muszę tak skonfigurować timer1 aby przerwanie występowało co 1us. Mam uC atmega328pu i kwarc 16MHz. Warości, które wpisuję do rejestrów porównania są na pewno poprawne, ale w moim przypadku dioda zmienia swój stan w czasie dłuższym niż 1s (dla testów w ISR umieściłem licznik ,który w momencie osiągnięcia warości 1 milion zmienia stan diody). Czy przerwanie tak często jest w możliwe? Czy musiałbym coś pozmieniać w hardware?
  • REKLAMA
  • #2 19376278
    piterek-23
    Poziom 33  
    antoniv10 napisał:
    Warości, które wpisuję do rejestrów porównania są na pewno poprawne, ale w moim przypadku dioda zmienia swój stan w czasie dłuższym niż 1s

    Mówisz, że na pewno wartości masz poprawne, ale chwilę później piszesz, że to nie działa ;)

    W mkAVRcalculator wychodzi coś takiego:
    Jak ustawić timer1 żeby przerwanie występowało co 1us?
  • #3 19376298
    krzysiek_krm
    Poziom 40  
    Cytat:
    The interrupt execution response for all the enabled AVR® interrupts is four clock cycles minimum. After four clock cycles the
    program vector address for the actual interrupt handling routine is executed. During this four clock cycle period, the program
    counter is pushed onto the stack. The vector is normally a jump to the interrupt routine, and this jump takes three clock
    cycles. If an interrupt occurs during execution of a multi-cycle instruction, this instruction is completed before the interrupt is
    served.

    Cytat:
    A return from an interrupt handling routine takes four clock cycles. During these four clock cycles, the program counter (two
    bytes) is popped back from the stack, the stack pointer is incremented by two, and the I-bit in SREG is set.

    Uzyskanie tak dużej częstotliwości przerwań jest raczej niewykonalne.
  • #4 19376317
    yego666
    Poziom 33  
    Jeśli jeszcze w przerwaniu zwiększasz jakiś licznik 32 bitowy, to całe przerwanie musi trwać pewnie ze dwie lub trzy mikrosekundy. Jeśli w tym czasie przyjdzie kolejne przerwanie to będzie czekało na zakończenie poprzedniego i tak dalej.
    W rezultacie Twój milion zostanie zliczony po czasie znacznie dłuższym niż sekunda i tak się właśnie u Ciebie dzieje.
    Ustaw dzielnik timera na wartość dziesięciokrotnie większą a w isr zliczaj do 100 000.
    Może otrzymasz wtedy właściwą wartość.
  • REKLAMA
  • REKLAMA
  • #6 19382832
    LED5W
    Poziom 34  
    Przy 16 MHz w 1 µs jest 16 taktów. Rozpoczęcie obsługi przerwania to minimum 4 takty, skok do procedury obsługi 3, odłożenie rejestrów na stos co najmniej 7, zdjęcie tyle samo, powrót z przerwania 4. Pisząc standardowo w C nawet pusta procedura obsługi przerwania nie zdąży się wykonać. Pisząc w asemblerze masz maksymalnie 8 taktów dla swojego kodu.
  • #7 19383026
    robiw
    Poziom 26  
    dondu napisał:
    antoniv10 napisał:
    ... muszę tak skonfigurować timer1 aby przerwanie występowało co 1us.

    Dlaczego musisz? Prawdopodobnie tu popełniasz błąd koncepcyjny.


    Też mi się tak wydaje. Nie bardzo znajduje uzasadnienie do tego by mieć przerwanie wywoływane tak często. Lepiej napisz, co chcesz przez to docelowo osiągnąć. R
  • #8 19384371
    antoniv10
    Poziom 3  
    Chciałem zrobić taką uniwersalną funckję, która będzie wstrzymywała program na określoną ilość us z wykorzystaniem timera.
  • #9 19384543
    khoam
    Poziom 42  
    antoniv10 napisał:
    Chciałem zrobić taką uniwersalną funkcję, która będzie wstrzymywała program na określoną ilość us z wykorzystaniem timera.

    Do tego wystarczy funkcja _delay_us(): Link
  • REKLAMA
  • #10 19384670
    BlueDraco
    Specjalista - Mikrokontrolery
    antoniv10 napisał:
    Chciałem zrobić taką uniwersalną funckję, która będzie wstrzymywała program na określoną ilość us z wykorzystaniem timera.


    I to jest właśnie ten błąd koncepcyjny. ;)
  • #11 19386382
    LED5W
    Poziom 34  
    Można do tego użyć timera, ale trzeba go ustawić tak, aby flaga przerwania została ustawiona raz (o ile czas nie jest zbyt długi). Dzięki użyciu timera, przerwania, które wykonają się w czasie takiej funkcji opóźniającej nie spowodują wydłużenia opóźnienia. Nie trzeba w tym celu pisać obsługi przerwania, wystarczy sprawdzać flagę. Chyba, że chcesz usypiać mikrokontroler. W każdym razie, szczególnie przy pojedynczych µs, każdy rozkaz jest istotny.
  • #12 19388822
    dondu
    Moderator na urlopie...
    antoniv10 napisał:
    Chciałem zrobić taką uniwersalną funckję, która będzie wstrzymywała program na określoną ilość us z wykorzystaniem timera.

    Projektując urządzenie wykorzystujesz jego zasoby (wewnętrzne moduły) w taki sposób, by spełniły wymagania jakie stawiasz przed urządzeniem.

    Tworzenie ogólnych (czytaj: do uniwersalnego zastosowania w różnych projektach) funkcji odliczających mikrosekundy w oparciu o timery jest generalnie pozbawione sensu.

    Timery są po to, by je wykorzystać tak jak w danym projekcie potrzebujesz. Jeśli więc będziesz potrzebował precyzyjnie odmierzyć czas np. 123us, to ustaw odpowiednio wybrany timer.

    Jeśli natomiast chcesz odmierzać odcinki czasu liczone w pojedynczych mikrosekundach, to najpierw powiedz nam do czego jest Ci to potrzebne, a powiemy Ci jak to powinieneś zrobić sprzętowo.

Podsumowanie tematu

Użytkownik stara się skonfigurować timer1 w mikrokontrolerze ATmega328PU, aby przerwanie występowało co 1 mikrosekundę, korzystając z kwarcu 16 MHz. Pomimo poprawnych wartości w rejestrach porównania, przerwanie nie działa zgodnie z oczekiwaniami, a dioda zmienia stan w czasie dłuższym niż 1 sekunda. Uczestnicy dyskusji wskazują, że osiągnięcie tak wysokiej częstotliwości przerwań jest trudne, a czas obsługi przerwania może wydłużać całkowity czas oczekiwania. Sugerują użycie dzielnika timera oraz funkcji _delay_us() jako prostszego rozwiązania. Podkreślają również, że projektowanie uniwersalnych funkcji opóźniających w oparciu o timery może być nieefektywne, a lepszym podejściem jest dostosowanie timera do konkretnych wymagań projektu.
Podsumowanie wygenerowane przez model językowy.
REKLAMA