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

[ATmega2560][C] - Modulacja jednego Timera drugim i dziwne "strzały"

Haz' 26 Cze 2013 01:18 1584 5
  • #1 12457086
    Haz'
    Poziom 12  
    Witam!

    Piszę program, w którym uruchamiam TIMER1 w trybie 15, działa on jako PWM ze stałą częstotliwością i wypełnieniem. Inicjuje TIMER3 który działa też w trybie 15 ale wywołuje z niego dwa przerwania, od porównania z rejestrem OCR3A i OCR3B. W pierwszym przerwaniu zeruje bit COM1B1 czyli wyłączam sterowanie portem przez TIMER1. W drugim przerwaniu ustawiam bit COM1B1 czyli ponownie włączam generacje PWM na porcie. Całość ma działać tak, że sygnał z TIMER1 moduluje sygnałem z TIMER3 ale niestety nie działa jak bym chciał. Port którym steruje TIMER1 mam podłączony do głośnika. Przy wyłączonej modulacji TIMERem3 wszystko działa czysto. Jak włączę TIMER3 to modulacja działa ale co kilka, kilkanaście sekund słychać dziwne trzaski, jakby TIMER1 nie zerował portu przy porównaniu z OCR1B. Próbowałem zamiast zerowania bitu COM1B1 poprostu ustawiać port PB6 jako wejście, a w drugim przerwaniu znowu jako wyjście ale nic to nie zmienia. Zatrzymywanie i startownie TIMER1 w przerwaniach też daje ten sam efekt.
    Kod poniżej, mam nadzieje że ktoś wpadnie na pomysł co jest nie tak, mi już brak pomysłów, z góry dzięki.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #2 12459561
    Andrzej__S
    Poziom 28  
    Tak na pierwszy rzut oka wydaje mi się, że problem może wynikać z tego, iż częstotliwość modulowana nie jest krotnością częstotliwości modulującej, przez co sygnał wyłączający wyjście PWM timera 1 przesuwa się względem fazy tego timera co w efekcie może powodować (co jakiś czas) wyłączenie sygnału na OC1B zaraz po ustawieniu na nim stanu wysokiego i w efekcie "trzaski".
    Zwróć uwagę, że okres zliczania timerów w trybie Fast PWM (15) nie jest równy OCRnA, tylko (OCRnA+1).
  • #3 12460477
    Haz'
    Poziom 12  
    To jednak nie to, rozwiązanie okazało się trywialnie proste, poprostu jak zeruje bit COM1B1 to czasami zostaje 1 na porcie i to powoduje te trzaski, wystarczy zerować także PB6. Pozostaje tylko pytanie, dlaczego ten problem występuje przy samym przestawianiu portu (we/wy) zamiast manipulacji bitem COM1B1?

    EDIT: niestety, problem nadal nie rozwiązany, pomimo zerowania PB6 wtedy kiedy bit COM1B1 nadal występują strzały ale teraz na innej częstotliwości modulacji i nie są to trzaski, ponieważ na oscyloskopie ma wyraźne długie impulsy prostokątne odróżniające się od reszty. Już nie mam pomysłów co robić dalej...
  • #4 12466691
    Andrzej__S
    Poziom 28  
    Dokumentacja Atmela nie opisuje bardzo precyzyjnie działania bloku "Waveform generator". Sugerując się jednak fragmentem:
    Atmel napisał:
    setting the COMnx1:0 = 0 tells the Waveform Generator that no action on the
    OCnx Register is to be performed on the next compare match

    można przypuszczać, że jeśli ustawisz bity COMnx1:0 na zero w momencie, gdy rejestr OCnx jest w stanie wysokim (patrz dokumentacja strona 147 rysunek (Figure) 17-5.) to pozostanie on w takim stanie. Jeżeli następnie ustawisz COMnx1:0 ponownie na wartość 2, to ten zapamiętany stan wysoki zostanie wystawiony na pin do momentu:
    Atmel napisał:
    A change of the COMnx1:0 bits state will have effect at the first compare match after the bits are written

    Jeżeli bity COMnx1:0 zostaną ustawione zaraz po porównaniu, które powinno wyzerować OCnx, to ten stan wysoki może trwać dosyć długo, biorąc pod uwagę, że w Twoim założeniu czas trwania stanu wysokiego na wyjściu OC1B jest stosunkowo krótki (OCR1A=1000, OCR1B=2 czyli 0,2% okresu).

    Próbowałeś może zastosować moją radę i ustawić timery synchronicznie (np. OCR1A = 999, OCR3A=19999)? Dobrze byłoby też dodatkowo ustawić wstępnie TCNT1 podczas inicjalizacji timera 1 na wartość 500. Spowoduje to, że przerwania timera 3, a więc i zmiany bitów COMnx1:0 będą przypadać zawsze w połowie okresu timera 1, czyli w momencie trwania stanu niskiego na pinie OC1B. Jeśli moje przypuszczenia są poprawne, to takie działania powinny dać pozytywny efekt.

    PS. Wystarczy ustawić raz bit 6 rejestru DDRB na 1 i PORTB na 0. Po ustawieniu bitów COM1B1:0 na wartość 0 na wyjściu PB6 musi być stan niski (patrz rysunek jak wyżej).
  • #6 12486113
    Haz'
    Poziom 12  
    Witam po długiej przerwie,
    strzały pojawiały się w dwóch sytuacjach, po ustawieniu bitów COM1B1:0 i po ich wyzerowaniu. W pierwszej sytuacji zgodnie z tym co pisał Andrzej, jak wyzerowałem wcześniej bity COM1B1:0 wtedy kiedy na wyjściu była jedynka i ustawiłem bity w czasie kiedy na wyjściu miało być zero to ta zapamiętana jedynka powodowała strzał - bo zmiana bitów COM1B1:0 daje efekt dopiero przy kolejnym porównaniu. Tutaj lekarstwem było zerowanie TCNT1 przed ustawieniem bitów COM1B1:0.
    W drugiej sytuacji kiedy zerowałem COM1B1:0 to na wyjściu czasami zostawała jedynka, dlatego w przerwaniu trzeba było dopisać zerowanie także PB6.
    Ustawienia synchronicznego timerów nie próbowałem bo potrzebuje dowolnie regulować częstotliwość modulującą a także modulowaną.
    Dziękuje wszystkim za pomoc.
REKLAMA