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...
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
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ć ?
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
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 ;]
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;
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 ???
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
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 ?
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