Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

ATmega32 - timer0 (CTC)ustawianie zadanej częstotliwości generacji przerwania

21 Gru 2012 22:04 3951 28
  • Poziom 13  
    Witam, chciałbym za pomocą timera0 pracującego w trybie CTC wywoływać przerwania z określoną częstotliwością by np migać diodą. Czy poniższe ustawienie timera jest poprawne i czego jeszcze brakuje?
    Jak za pomocą preskalera być w stanie ustawiać częstotliwości między 1Hz-50kHz?
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 21  
    Przede wszystkim funkcja long zadana częstotliwość nic nie robi. I jest błędna, ponieważ nie zwraca żadnej wartości.

    Po drugie lepiej wyglądało by to tak:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Przede wszystkim co rzuca się jeszcze w oczy to fakt, że nie zależnie od tego co zwróci twoja funkcja, starasz się zapisać liczbę 32 bitową (Typ long) do 8 bitowego rejestru.
  • Poziom 13  
    Czyli do OCR0 moge wpisać max 0xFF?? W ATmega32 preskaler jest 10 bitowy ale jak to się ma do ustawiania częstotliwości? Jeżeli clk =16MHz a program wyżej (chyba) ustawial clk/64 czyli 250kHz. Tzn że to jest najmniejsza do osiągnięcia częstotliwość na tym ustawieniu? Gdzie w tym wszystkim rola preskalera?
  • Poziom 21  
    To, że sygnał CLK można podzielić przez 1024 (maksymalnie), to nie oznacza, że rejestr jest 10 bitowy. Jest to rejestr 8 bitowy i w dodatku jest to w tym przypadku rejestr TCCR0.

    Proponuję również zacząć od napisania funkcji pozwalającej zmienić częstotliwość w mniejszym zakresie. Np od 100 Hz do 500 Hz.

    Tak, do rejestru OCR0 możesz wpisać maksymalnie wartość 255 (0xFF).

    W przypadku ustawienia prescalera na 256 powinieneś otrzymać częstotliwość około 244 Hz.

    Maksymalnie swój sygnał CLK możesz podzielić przez 1024 i później ustawiając OCR0 na 255, minimalną częstotliwość otrzymasz równą około 61 Hz. Przy nie zmiennym prescalerze zakres jaki będziesz miał do do dyspozycji równy będzie od 61 Hz do około 15kHz. Pamiętaj jednak, że im większy dzielnik w prescalerze, tym mniejsza dokładność.
  • Poziom 13  
    Czegoś tu nie rozumiem.
    Ok, wiem jak doszedłeś do tych prawie 244Hz, z tego co rozumiem 244Hz będzie przy OCR0 = 255; więc jak to jeszcze zmniejszyć? skoro wielkość rejestru na to nie pozwala?
  • Poziom 21  
    Możesz użyć licznika 16 bitowego (Timer1). Wtedy minimum to teoretycznie 0.25 Hz.

    Możesz też w przerwaniu nie zmieniać stanu portu, tylko np. inkrementować zmienną. Czyli tak w najprostszym rozwiązaniu:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Powyższe rozwiązanie nie jest optymalne (Funkcja przerwania powinna być jak najbardziej zwięzła), ale pokazuje o co chodzi.

    Swoją drogą zmienną można dobrać tak, aby uzyskać duży zakres, można również w takim przypadku sterować tym zakresem i zmienna nie musi być 8 bitowa. Takie rozwiązanie pozwoli również ustawić mniejszą wartość prescalera, a więc częstotliwość będzie dokładniejsza.
  • Poziom 13  
    Zastanawiam się tylko czy możliwym jest uzyskać zakres 1Hz-1MHz, przy niewielkiej (<10%) dokładności obliczenia częstotliwości
  • Poziom 21  
    Wszystko zależy od tego, jak napiszesz program oraz którego z timerów użyjesz. Nie wiem, czy przy 1 Hz (Tu spodziewam się największego błędu), otrzymasz błąd mniejszy niż 10%. Spodziewam się, że tak. Tylko po co ci tak duży zakres zmiany częstotliwości?
  • Poziom 13  
    Takie dostałem zadanie. Ma być możliwość próbkowania danych z pinu z częstotliwością od 1Hz - 1MHz. Siedzę w Excelu i liczę jak by to poustawiać żeby miało ręce i nogi ale coś mi nie idzie.

    Dodano po 1 [godziny] 53 [minuty]:

    Realnie chciałbym aby była możliwość ustawiania czestotliwości co 100Hz na zakresie 1kHz-100kHz. Mógłby mi ktoś pomóc dobrać wartości preskalera, OCR0, i sposobu obliczania zmiennej w przerwaniu?
  • Poziom 21  
    Przecież prescaler również można zmienić. Po za tym. Przecież można ustawić prescaler na CLK/8. A potem zmieniać wartość reload i otrzymasz zakres od 1 Hz, do 1 Mhz.

    W końcu nie wiem, czy zakres ma być 1 do 1 MHz, czy 1 k do 100 kHz?

    Dla tego drugiego sprawa jest banalnie prosta. Ustawiam prescaler na wartość CLK/8. DO OCR0 wpisuje wartość 20, więc otrzymuję maksymalną częstotliwość równą 100 kHz. I teraz wprowadzam sobie do warunku if(reload>=60), zamiast 60 dodatkową zmienną, za pomocą której mogą już regulować wartość częstotliwości na wyjściu.
  • Poziom 13  
    To tak nie zadziała. reload =1 i mam 100kHz reload = 2 i mam 50kHz reload = 3 i mam 33,(3) kHz a chce od 1kHz do 100kHz mieć możliwość ustawiać częstotliwość co 100Hz
  • Poziom 21  
    No tak masz rację. Ale powiem Ci, że wartości 99900 Hz w ten sposób w ogóle nie da się tutaj osiągnąć przy zegarze 16 MHz i z użyciem jednego timera ;)
  • Specjalista - Mikrokontrolery
    Możesz ustawić tylko taką częstotliwość przerwań, która da się opisać wzorem f = Fclk / Pre / Period, gdzie Fclk jest częstotliwością zegara procesora, Pre - wartością preskalera timera - masz kilka do wyboru - sprawdź w dokumentacji Twojego procesora, Period - okres timera - 1..256 dla 8-bitowego, 1..65536 dla 16-bitowego.
    Zacznij od wyboru timera - jest ich kilka.
    Praktycznie maksymalna użyteczna częstotliwość będzie rzędu Fclk / 50 jeśli oprogramujesz to przyzwoicie w C.
  • Poziom 21  
    Swoją drogą zastanawia mnie po co to masz zrobić?

    Bo ogólnie jeśli chodzi o realizację problemu, to robi się to za pomocą układów PLL, i to w kilku sekcjach, jeśli zakres jest duży, a krok mały.

    Po za tym jeśli chodzi o próbkowanie pinu to, po co zmieniać częstotliwość próbkowania w zakresie od 1k do 100k, jeśli może być od razu 100k, ważne tylko, aby była przynajmniej dwa razy większa od częstotliwości próbkowanego sygnału.
  • Poziom 13  
    ponieważ urządzenie podłączone do tego pinu działa z częstotliwością 100kHz. A zazwyczaj jest potrzeba zbierać próbki rzadziej. i żeby nie trzeba było za każdym razem ustawiać dwóch/trzech wartości i ładować nowego programu do mikrokontrolera to chciałem zrobic to programowo. Jak widzę nie da się.
  • Specjalista - Mikrokontrolery
    Ależ oczywiście, że się da, trzeba tylko wykonać w programie parę prostych obliczeń - z 10 linii kodu powinno wystarczyć. No i oczywiście zadawać jako parametr okres próbkowania, a nie częstotliwość.
  • Poziom 21  
    Możesz bardziej rozwinąć swoją wypowiedź?
  • Poziom 27  
    Przecież możesz to zrobić tak:
    Zaprogramować timer aby zglaszał przerwanie co np 1us ( trzeba by było dać kwarc o dużej częstotliwości). W przerwaniu tylko Licznik++, gdzie Licznik jest typu long.
    W głównym programie wystarczy tylko przeliczyć częstotliwość na okres w us i porównywać ze zmienną Licznik. Jeśli Licznik > Okres zerujesz zmienną Licznik i zmieniasz stan portu.
    Problem może dotyczyć górnych częstotliwości, bo trzeba by było zrobić przerwanie co 0.5us aby uzyskać czestotliwość 1MHz. Zatem aby sprostać takim czasom trzeba napisać bardzo szybki program.
    W ten sposób da się zrobić generator w zakresie od 1Hz do rzedu 1Mhz.
  • Poziom 36  
    Sparrowhawk napisał:
    No tak masz rację. Ale powiem Ci, że wartości 99900 Hz w ten sposób w ogóle nie da się tutaj osiągnąć przy zegarze 16 MHz i z użyciem jednego timera ;)


    Na pewno? (!)
    Popatrz więc na fragment Datasheet (dolna częśc str.72)
    "For generating a waveform output in CTC mode, the OC0 output can be set to toggle its logical level on each compare match by setting the Compare Output mode bits to toggle mode (COM01:0 = 1). The OC0 value will not be visible on the port pin unless the data direction for the pin is set to output. The waveform generated will have a maximum frequency of fOC0 = fclk_I/O/2 when OCR0 is set to zero (0x00). The waveform frequency is defined by the following equation:
    ATmega32 - timer0 (CTC)ustawianie zadanej częstotliwości generacji przerwania


    wstaw więc do powyższego wzoru za:
    f(clk)_I/O = 16 000000 (16 MHz)
    N =1 (prescaler)
    oraz
    OCR0 = 79 (możesz próbowac z 80 i 81 lub inne wartości w zakresie 0 do 255 )
    i oblicz....
    Oczywiście nie uzyska szukanej rozdzielczości (co 100Hz) z uwagi na zbyt "krótki" timer, odchylenia czestotliwości będa w zbyt dużym rozrzucie; jak równięz nie jest możliwe osiągnięcie projektowanego zakresu (1 kHz do 100kHz)_ przy stałym ustawieniu prescalera.

    e marcus
  • Poziom 21  
    No tak właśnie o ten wzór oparłem swoją wypowiedź.

    Dla 79 dostanę: 100 kHz.
    Dla 80 dostanę: 98.765 kHz.
    Dla 81 dostanę: 97.560 kHz.

    Z tego już widać, że częstotliwości 99.900 kHz, jak i tym bardziej 99.000 kHz czy 98.000 kHz nie otrzymamy.
  • Poziom 13  
    A jak chcesz ustawić preskaler =1? Skoro odpowiedni rejestr umożliwia tylko clk/(8,64,256,1024)??
  • Poziom 36  
    mikroice90 napisał:
    A jak chcesz ustawić preskaler =1? Skoro odpowiedni rejestr umożliwia tylko clk/(8,64,256,1024)??


    CS02=0, CS-01=0, CS0=1
    Tabela42 str 82 drug wiersz

    e marcus
  • Poziom 21  
    Co nie zmienia faktu, że nie dostaniesz 99.900 kHz, ani 99.000 kHz, ani 98.000 kHz itd. :P
  • Poziom 13  
    to jak masz no preskaling to preskaler = 1?
  • Poziom 36  
    Sparrowhawk napisał:
    Co nie zmienia faktu, że nie dostaniesz 99.900 kHz, ani 99.000 kHz, ani 98.000 kHz itd. :P


    No właśnie co napisałem w korekcie mojego postu powyżej odnośnie rozdzielczości.

    Kilka postów poniżej jest 'równoległy' temat :
    https://www.elektroda.pl/rtvforum/topic2449621.html#11674022
    proponowałbym śledzic jego dyskusję, ewentualnie dołączyc tam....
    zamiast powielac to samo.

    e marcus

    Dodano po 15 [minuty]:

    mikroice90 napisał:
    to jak masz no preskaling to preskaler = 1?


    Tak, dokładnie znaczy to że clock sygnał nie jest dzielony przez prescaler (jest pdłączony bezpośrednio do timera). Por. rys 39 str 85 - patrz wejście do bloku lolgicznego kontroli Timera0 - pierwsza strzałka po prawej -obok indeksu 0.
  • Poziom 21  
    Masz rację, nie doczytałem. Temat, który podałeś ma podobny charakter, ale funkcja układu jest inna.

    Natomiast tutaj. Nie widzę nic złego w tym, aby próbkować sygnał wolno zmienny dużą częstotliwością. Pytanie jeszcze jaki sygnał próbkujemy? Czy jest to sygnał cyfrowy, czy analogowy? Jeżeli analogowy, to z jaką dokładnością mamy go próbkować? Być może warto sięgnąć po nieco inne rozwiązania, jak np. wykrywanie zmian sygnału i w tym momencie dokonywanie jego odczytu?
  • Poziom 13  
    sygnał cyfrowy, próbkowanie musi być w miarę dokładne (max 2% błedu)
  • Poziom 21  
    Czegoś tu nie rozumiem.

    1. Do pinu w ATmega32 podłączone jest urządzenie, które jest źródłem sygnału cyfrowego?
    2. Sygnał może mieć maksymalną częstotliwość 100 kHz?
    3. Nie chcesz próbkować go, stale z prędkością 200 kHz, bo sygnał czasami zmienia się wolniej?
  • Poziom 13  
    Zazwyczaj istnieje potrzeba zbierania próbek wolniej z uwagi na to żeby zbierać odpowiednie bity. Jeśli zbieranie będzie za szybkie wtedy będę miał zbyt dużo długich serii obok siebie