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

sterowanie czestotliwoscią atmega32

qudi 24 Mar 2010 17:07 1809 16
REKLAMA
  • #1 7874741
    qudi
    Poziom 15  
    Witam !!!
    Ostatnio bawiłem się troszkę przetwornikiem ADC, i mam teraz problem gdyż chcę napięciem sterować częstotliwość w granicach od 1 kHz do 5 kHz (tzn chce zrobić U/f)... nie mam za bardzo pojęcia jak się za to zabrać gdyż dopiero zaczynam zabawę z uC... (czytam coś o pwm na atmega32 ale nie mogę pojąć do czego slużą te poszczególne rejestry)

    proszę o pomoc

    Dodano po 15 [minuty]:

    jeśli mógłby ktoś pomóc chociaż w kwestii PWM jak go się ustawia i jak nim można sterować to byłbym wdzięczny...
  • REKLAMA
  • #2 7875145
    krzychS
    Poziom 29  
    Rejestry służą do ustawienia Timera. Dokładny opis ich funkcji znajdziesz w notach katalogowych uC.

    Napisz w jakim języku chcesz to zaprogramować.
  • #3 7876831
    qudi
    Poziom 15  
    Chcę to wykonać w C, średnio znam angielski i przez to ciężko mi to załapać... No ale czytam jak mogę ;] Jeśli ktoś ma linka do czegoś z tym związanym po polsku to będę wdzięczny
  • REKLAMA
  • #6 7877740
    qudi
    Poziom 15  
    Mam jeszcze jedno pytanie, czy jak zacznę się bawić tymi rejestrami i ustawiać te liczniki to mogę jakoś sprawdzić czy to działa ? Np. w symulatorze bądź za pomocą miernika częstotliwości ??? Tylko to będą sygnały prostokątne to nie wiem czy zwykły miernik się na coś zda. Więc jak to sprawdzać ?
  • #7 7877754
    _Robak_
    Poziom 33  
    AVRstudi ma wbudowany symulator, tyle że akurat z timerami miał kłopoty, nie wiem jak teraz.
  • REKLAMA
  • #8 7877781
    qudi
    Poziom 15  
    a taki miernik częstotliwości odpada ?
  • REKLAMA
  • #9 7877974
    davidpi
    Poziom 10  
    A AVRStudio 4 powinna działać symulacja PWM. Ale jest jeden szkopuł. Możesz generować sygnał PWM o zadanym wypełnieniu, ale ciężko dokładnie ustawić okres sygnału. W rzeczywistym układzie wszystko będzie działać OK, ale w symulacji nie koniecznie. Jeżeli chcesz przeprowadzić symulację, to w parametr OCRxx możesz wpisać dowolną liczbę, natomiast wartość TOP (czyt. wartość do której licznik zlicza) w symulacji nie da się ustawić. To jednak nie powinno Ci przeszkodzić w zrobieniu symulacji. Natomiast musisz pamiętać, że symulacja odbywa się znacznie wolniej niż układ działa w rzeczywistości, dlatego proponuję używać licznika 8-bitowego podczas symulacji. Pozdrawiam
  • #10 7878079
    qudi
    Poziom 15  
    Dzięki, (rozumiem że do symulacji mogę używać 8 bitowego licznika jednak w rzeczywistości potrzebuje 16 bitowego), mam kolejne pytanie otóż przeczytałem takie coś:

    "Zerowanie licznika w trybie porównania (Tryb CTC - czyszczenia zegara):

    (...)Jeżeli wpisana nowa wartość do OCR1A lub ICR1 jest mniejsza od aktualnej wartości w TCNT1, licznik opóźni proces porównania. Licznik będzie musiał zliczy do wartości maksymalnej (0xFFFF) i po wyzerowaniu zliczy do wartości przy której wystąpi porównanie."

    I stąd moje pytanie czy ten fakt że on będzie liczył do 0xFFFF spowoduje jakiś chwilowy przestój/bezczynność w generowaniu impulsu widoczny w użytkowaniu jakiegoś urządzenia? czy będzie to działało ładnie... ??? ile mniej więcej trwa takie zliczenie do max czyli w tym wypadku do 0xFFFF ??? i jeszcze jedno czy myślicie że obrałem dobry typ pracy licznika czyli CTC ???

    Dziękuje za pomoc i przepraszam jeśli pytanie są dziwne ;]
  • #11 7878664
    davidpi
    Poziom 10  
    Jeżeli chodzi o to że musisz używać licznika 8-bitowego. Po prostu w symulacji musiał byś czekać kilkadziesiąt minut zanim licznik zapełnił by 16 bitów. Z 8-bitowym pójdzie sprawniej :)

    Jeżeli chodzi o drugą sprawę to nie mam pewności, więc proszę o weryfikację bardziej doświadczonych kolegów, ale postaram się dać przykład według mojego rozumowania :).
    Otóż załóżmy że masz licznik który pracuje w trybie CTC. Zlicza on od zera do wartości ustalonej w rejestrze ICR1 ( lub OCR1x) i w momencie gdy się doliczy do tej wartości ustawia flagę ewentualnie bit. Załóżmy że wartość ICR1 wynosi 50000. W danej chwili czasu w twoim liczniku jest wartość 40000. W tym momencie przychodzi rozkaz ICR1=10000. W rejestrze ICR1 masz teraz wartość 10000. Licznik liczy cały czas w górę, lecz nie napotyka wartości porównania. Dochodzi do swojego max równego 65535 i się zeruje i od nowa liczy. Po dojściu do wartości 10000 ustawia flagę i ewentualnie bit. Wiec wniosek jest taki, że jedna pętla licznika nie zakończyła sie porównaniem i generowaniem impulsu. Można się próbować zabezpieczyć przed tym zmieniając wartość rejestru ICR1 w chwili gdy stan licznika ( czyli zawartość rejestru TCNT1) jest równa 0;
  • #12 7878740
    qudi
    Poziom 15  
    Ale czy ktoś się orientuje czy taka właśnie sytuacja spowoduje jakiegoś rodzaju dłuższy przestój w wysterowaniu ?
  • #13 7878771
    Konto nie istnieje
    Poziom 1  
  • #14 7878805
    qudi
    Poziom 15  
    No tak to na pewno, ale chodzi mi o to czy będzie jakiś dłuższy przestój ? Czy w jakiś milisekundach ? Jak ma się to zliczanie do czasu rzeczywistego ? Ile trwa zliczenie całych 16 bitów dla licznika ???
  • #15 7879206
    davidpi
    Poziom 10  
    To wszystko zależy od tego jaki masz kwarc i jaki ustawisz preskaler. Zakładając że masz kwarc 1MHz i zliczasz bez preskalera to wtedy jeden pełny cykl licznika (65536 impulsów) będzie trwał 65,5 ms. W najgorszym przypadku (czyli wtedy gdy masz kwarc 1MHz, chyba najwolniejszy ze standardowych:) , i preskaler 1024) to jeden impuls zegara trwa ok 1ms, a zatem cały cykl to ponad minuta.
    Czy to jest dużo czy mało, to już musisz sam ocenić hehe :)
  • #16 7879294
    qudi
    Poziom 15  
    Napisałem taki kod... Sygnał wyjściowy chce mieć na PD5, resztę widać chyba w komentarzach, nie wiem jak takie coś z testować, poza tym brakuje tego całego porównania licznika z wartością gdyż nie wiem jak to zrobić za bardzo... Oraz czy dobrze i wystarczająco skonfigurowałem rejestry mi potrzebne do sterowania częstotliwością sygnału prostokątnego ?

    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
    
    int main() {
    
    DDRD = 0b00100000;
    
    TIMSK = (TOIE1 <<1)|(OCIE1A <<1); // wlaczenie przerwan od przepelnienia
    								  // i porownania licznika T1
    
    TCNT1 = 0x0000;					  // inicjalizacja licznika
    	
    TCCR1A = 0x0000;				  // OC1A/OC1B odlaczone, zwykly tryb pracy
    TCCR1B = _BV(CS10);		  		  // bez preskalera
    
    sei();							  // wlaczenie przerwania
    
    while(1) {
    
    }
    
    return(0);
    }
    


    Dodano po 42 [minuty]:

    Czy mógłby ktoś podpowiedzieć jak to z testować przy użyciu jakiś migających diód, i jak należy porównywać ten licznik z zadaną wartością ?
  • #17 7879862
    davidpi
    Poziom 10  
    Otóż tak. Sprawa się ma następująco.
    Rozuiem że chcesz na wyjściu otrzymać sygnał prostokątny o wypełnieniu 50% i regulowanej częstotliwości.
    Ja proponowałbym takie rozwiązanie:
    
    #include <avr/io.h>
    int main()
    {
    	DDRB=0xff; //Port B jako wyjście
    	TCCR1A=_BV(COM1A0); //wyjście OC1A jest przełączane przy osiągnięciu wartości OCR1A
    	TCCR1B=_BV(WGM12) | _BV(CS10); //Tryb CTC, Bez preskalera
    	OCR1A=200; //Wartość do porównania
    	while(1)
    	{
    	}
    	return 0;
    }
    

    Można użyć trybu CTC. Gdy licznik doliczy do jakiejś wartości, określonej w OCR1A wyjście OC1A zostanie zmienione na przeciwne. W każdej chwili można zmienic wartośc OCR1A zmieniając przy tym częstotliwość. Należy pamiętać że wartość OCR1A odpowiada połowie okresu, czyli odcinkowi czasu pomiędzy poszczególnymi zmianami stanu na wyjściu.

    Teraz kolejna sprawa:
    Jeżeli chcesz mieć sygnał koniecznie na wyjściu PD5 to trzba posłużyć się innym kodem.
    Proponuję użyć przerwań.
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    int main()
    {
    	DDRB=0xff; //Port D jako wyjście
    	TCCR1B|=((1<<WGM12) | (1<<CS10)); //Tryb CTC, Bez preskalera
    	OCR1A=200; //Wartość do porównania
    	TIMSK|=(1<<OCIE1A); //Zezwolenie na przerwanie od porównania z wartością OCR1A
    	sei(); //Globalne zezwolenie na przerwanie
    	while(1)
    	{
    	}
    	return 0;
    }
    ISR(TIMER1_COMPA_vect) // Obsługa przerwania
    {
    	PORTD ^=(1<<5); //Zmiana stanu na przeciwny
    }
    

    Efekt powinien być podobny do poprzedniego, choć przyznam się, że akurat ten program nie chciał mi działąć podczas symulacji.

    Dodano po 10 [minuty]:

    Natomiast nawiązując do Twojego poprzedniego pytania, w którym martwiłeś się o ten jeden pusty cykl. Otóż można się przed nim bardzo łatwo bronić. Tylko wtedy nie należy używać trybu CTC, tylko trzeba użyć trybu PWM. W trybie CTC wartość OCR1A jest zmieniana natychmiast po wystąpieniu rozkazu zmiany. Natomiast w trybie PWM wartość OCR1A jest zmieniana w jednej ściśle określonej chwili czasu. To znaczy: niezależnie od tego, w którym momencie cyklu wystąpi rozkaz zmiany tej wartości, układ i tak poczeka aż licznik zliczy do maksimum ( lub minimum ) i dopiero wtedy nastąpi zmiana. Jest to jakiś sposób obrony przed Twoim problemem.

    Natomiast nawiązując do ostatniego pytania, o którym zapomniałem :) , czyli o testowanie za pomocą diody. Otóż da się to zrobić. W którymś z moich programów podłącz diodę do danego wyjścia. Ważne jest aby częstotliwość nie byłą większa niż 10Hz, bo nie zobaczysz czy dioda miga czy nie. Trzeba w OCR1A wpisać odpowiednio dużą wartość i ustawić odpowiednio duży preskaler. NP. dla kwarcu 1MHz i preskalera 1024 jeden impuls to ok. 1 ms. Zatem możesz spokojnie wtedy ustawić OCR1A na 1000. Dioda będzie migać raz na dwie sekundy.

    Dodano po 3 [minuty]:

    A tu masz fajną stronkę z opisem Timerów. Jest tam opisane kilka sposobów migania diodą, co tak naprawdę jest generowaniem fali prostokątnej o pewnej częstotliwości
    http://www.wkretak.pl/readarticle.php?article_id=3
    Pozdrawiam
REKLAMA