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][C] Obmierzanie czasu z dokładnością do 0.1ms

ullman 23 Cze 2010 18:05 1187 8
REKLAMA
  • #1 8223194
    ullman
    Poziom 11  
    Witam,
    Chciałbym opóźnić załączenia urządzenia o 69800us (wartość zapisana w zmiennej)
    Jak to zrobić z dokładnością do 0.1ms? Rozwiązanie za pomocą pętli for i delay_us odpada bo wprowadzi to dodatkowe błędy związane z wykonaniem pętli for (3 takty zegara). Podzielenie wartości przez 1000 też nie wiele da bo otrzymam 69ms Proszę o rade:)
  • REKLAMA
  • #2 8223273
    tmf
    VIP Zasłużony dla elektroda
    Nie przesadzaj, z jakim zegarem taktujesz procesor? Jeśli nawet tylko 1MHz, to 3 takty to zaledwie 3mikros. A jak potrzebujesz super dokładność to użyj timera i wyjścia OCx. Możesz zaprogramować zmianę jego stanu z dokładnością do taktu zegara z uwzględnieniem preskalera timera.
  • REKLAMA
  • #3 8223348
    ullman
    Poziom 11  
    3 us* 69800 = 209,4ms wiec jest to znacząca różnica. Jak za pomocą timera rozumiem poprzez porównanie tego czasu z aktualną zawartością liczka timera?
  • REKLAMA
  • #4 8223423
    tadzik85
    Poziom 38  
    Jakim cudem mnożysz ten czas razy 3? a licznikiem bardzo dużo dokładniej zmierzysz ten czas. ustawiasz wartość początkowa preskaler i czekasz az się przepelni
  • REKLAMA
  • #5 8223553
    ullman
    Poziom 11  
    Mnożę ten czas razy 3 bo 3us trwa wykonie pętli for, a pętla for będzie wykonywana 69800 bo for (i=0, i<69800, i++) delay_us(1) end
  • #6 8223554
    janbernat
    Poziom 38  
    Np. tak:
    Ustawiasz zegar na 1Mhz
    W main() ustawiasz:
    Zezwolenie na obsługę przerwań
    Zezwolenie na obsługę przerwań od Timer0 (albo Timer2)
    Prescaler na 1
    Sprawdzenie jakiejś flagi
    A w obsłudze przerwania ovf od Timer0 (albo 2):
    Do rejestru Timer0 (albo 2)
    wpisujesz 156.
    Wtedy przerwanie występuje co 0.1ms i ustawi jakąś flagę.
    Wtedy w main() decydujesz co zrobić.
  • #7 8226696
    gaskoin
    Poziom 38  
    btw czemu się tak upierasz przy tym, aby funkcje delay wywoływać z parametrem 1, można tam wpisać dowolna liczbę typu double

    więc czemu nie

    _delay_ms(t/1000.0) ?
  • #8 8228926
    rpal
    Poziom 27  
    janbernat napisał:
    Np. tak:
    Ustawiasz zegar na 1Mhz
    W main() ustawiasz:
    Zezwolenie na obsługę przerwań
    Zezwolenie na obsługę przerwań od Timer0 (albo Timer2)
    Prescaler na 1
    Sprawdzenie jakiejś flagi
    A w obsłudze przerwania ovf od Timer0 (albo 2):
    Do rejestru Timer0 (albo 2)
    wpisujesz 156.
    Wtedy przerwanie występuje co 0.1ms i ustawi jakąś flagę.
    Wtedy w main() decydujesz co zrobić.

    nie zgodzę się z kolegą bo o czymś kolega zapomniał. Opóźnienie ma być o 69800us czyli po wykonaniu 698 razy obsługi przerwania w.w. Timera. Na moje oko zdecydowanie lepiej jest w epilogu programu zdefiniować wszystko co trzeba dla wybranego licznika, potem włączyć zezwolenie na wykonywanie przerwania co 0,1ms z ta tylko różnicą że obsługa przerwania powiększa zmienną globalną (od zera do 698) i z chwilą przekroczenia tej wartości , w obsłudze przerwania należy ustawić flagę dla głównego programu. Tego moim zdaniem zabrakło w tym algorytmie. Z kolei główny program wchodzi w pętlę do czasu ustawienia flagi. Dalej musi nastąpić wyłaczenie Timera aż do następnej okazji. Z tego co napisałeś program główny musiałby sam już zadbać aby co 0,1ms powiększać jakąś zmienna a po co skor omoże to załatwić jeszcze obsługa przerwania Timera?
  • #9 8229533
    janbernat
    Poziom 38  
    Co do inkrementowania zmiennej , ustawiania flagi po osiągnięciu zadanej wartości- pewnie że może być w przerwaniu.
    Zależy od wymagań- albo minimalizujemy czas obsługi przerwania a część decyzyjną dajemy w głównej pętli- albo nie zależy nam bardzo na czasie obsługi przerwania i całą procedurę dajemy w przerwaniu.
REKLAMA