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

[AVR] Dlaczego sygnał prostokątny z Timer2 w ATmega8 ma 6,5 kHz zamiast 125 kHz?

eivon 04 Wrz 2012 23:17 1725 7
REKLAMA
  • #1 11279689
    eivon
    Poziom 9  
    Witam,
    mam pytanie odnośnie timera w atmega8. Zdefiniowałem w programie dla Timer2 tryb pracy CTC i bez preskalera (TCCR2 = _BV(WGM21) | _BV(CS20)) oraz generowanie przerwania przy zliczeniu do 4 (OCR2 = 4). Nie dokonywałem żadnych zmian przy zegarze wewnętrznym z którego korzystam, zatem z tego co wiem ma on częstotliwość domyślną 1MHz. Przerwanie polega na zmianie stanu portu na przeciwny.
    Działając w ten sposób, wg mnie teoretycznie, powinienem uzyskać na wyjściu sygnał prostokątny o częstotliwości 125 kHz (częstość zmian to 250 kHz, okres sygnału prostokątnego jest dwa razy dłuższy). Jednak sprawdzając oscyloskopem uzyskuję sygnał 6,5 kHz.
    Gdzie popełniłem błąd?
    Pozdrawiam
  • REKLAMA
  • Pomocny post
    #2 11279836
    kiziu13
    Poziom 17  
    Zacznij od pokazania całego kodu. Jeśli korzystasz z przerwań, to najprawdopodobniej mikrokontroler nie wyrabia i powoduje opóźnienia. Policz sobie (BTW, przy OCR2 = 4, dostajesz 100kHz, popatrz na wzór, należy do OCR2 dodać jeden przed dzieleniem), przy częstotliwości 100kHz, procesor ma 10 taktów na obsłużenie przerwania, co na pewno trwa dłużej, zważywszy na konieczność wykonania skoku, zapisaniu na stosie rejestrów, a następnie wykonania kodu, odtworzenia rejestrów i powrotu do programu. Jeśli potrzebujesz tak dużej częstotliwości, to albo zwiększ zegar systemowy, albo zastosuj w pełni sprzętową obsługę wyjścia, tj. zmianę stanu pinu OC2 przy porównaniu.

    EDIT: Mały błąd, zapatrzyłem się na wzór do generowania przebiegów za pomocą CTC przy liczeniu częstotliwości. W przypadku, gdy generowane jest tylko przerwanie, to oczywiście częstotliwość wywoływania przerwań będzie równa 200kHz, co daje jeszcze mniej, bo 5 taktów pomiędzy kolejnymi przerwaniami.
  • REKLAMA
  • #3 11279866
    eivon
    Poziom 9  
    Wrzucam to co kluczowe, włączanie timera2 w przerwaniu pierwszego. Mam nadzieję, że nie walnąłem się teraz w pisaniu kodu ale na 90% podczas sprawdzania wyglądał on tak

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • Pomocny post
    #4 11279884
    kiziu13
    Poziom 17  
    Nie zagłębiam się o co dokładnie chodzi w kodzie, bo to i tak fragmenty, ale nie ma żadnych szans, żeby mikrokontroler był w stanie wyrobić z taką częstotliwością przerwań. Tak jak pisałem wcześniej, musisz zmienić podejście, ale wnioskując z fragmentów kodu, w grę wchodzi jedynie zwiększenie zegara systemowego, prawdopodobnie połączone z trybem CTC i sprzętową generacją przebiegów, co pozwoli odciążyć mikrokontroler.

    Masz dodatkowo parę innych błędów, m.in. w init() masz odejmowanie zamiast przypisania. Ponadto, korzystasz ze zmiennych typu int, a wykorzystujesz jedynie zakres char, co powoduje zwolnienia. Lepiej w tym wypadku samemu dobrze wybierać typy, niż polegać na optymalizatorze.
  • #5 11279893
    eivon
    Poziom 9  
    Dzięki wielkie, tak jak pisałem mogły wkraść się jakieś tego typu błędy bo pisałem bez kompilowania. Poprawię te wartości int.

    Korzystam ze środowiska WinAVR, rozumiem, że muszę zmienić fuse bity CKSEL. Jak to zrobić przy pomocy tego środowiska? Da radę poszukać gdzieś w opcjach, trzeba dopisać jakiś kod do MakeFile'a czy ściągnąć jakąś dodatkową aplikację? Jeszcze nigdy tego nie robiłem, a dopiero co zaczynam przygodę z programowaniem uC.

    Pozdrawiam
  • Pomocny post
    #6 11279901
    kiziu13
    Poziom 17  
    Fuse bitów nie zmienia się z poziomu środowiska, ale z poziomu programu wgrywającego kod na mikrokontroler, wyjątkiem jest, kiedy środowisko ma zintegrowany program wgrywający, albo przynajmniej obsługę jako zewnętrznego narzędzia. Pomocną stroną do konfiguracji fuse bitów jest np. http://www.engbedded.com/fusecalc/ , chyba, że program wgrywający, którego używasz posiada edytor fusebitów, jak np nakładka Burn-O-Mat http://avr8-burn-o-mat.aaabbb.de/avr8_burn_o_mat_avrdude_gui_en.html na program AVRdude. Oczywiście to, jakiego programu użyjesz, nie wpłynie na efekt końcowy, najważniejsze, żeby dobrze wybrać wartości fuse bitów. Podpowiedź: należy wybrać wewnętrzny oscylator o f = 8MHz. Jeśli potrzebujesz szybszego zegara systemowego, musisz skorzystać z zewnętrznego źródła, jak np. rezonator kwarcowy. Maksymalną, gwarantowaną przez producenta co do poprawnego działania, częstotliwość zegara systemowego znajdziesz w nocie katalogowej,
  • REKLAMA
  • #7 11279906
    eivon
    Poziom 9  
    Super, dzięki.
    Przy instalacji WinAVR dostałem w pakiecie AVRDUDE. Wchodząc na pierwszy link, który mi podałeś, wybrałem mój mikrokontroler: Atmega8 i w features zmienilem tylko jedna opcje z trzech dostepnych list a mianowicie wewnętrzny RC 8 MHz, CKSEL 0100 SUT 00. Na dole pozaznaczały się odpowiednie wartości (nie wiem czy te z prawej są niezbędne). Do czego zmierzam: na samym dole wykreował się zapis AVRDUDE arguments. Jeżeli dobrze rozumiem, mogę wpisać w "cmd" "avrdude -U lfuse:w:0xc4:m -U hfuse:w:0xff:m" dzięki czemu wgrane zostaną te ustawienia?
  • #8 11279911
    kiziu13
    Poziom 17  
    Niestety, ale są to złe wartości. To co podałeś, spowoduje wyłączenie możliwości programowania szeregowego, bit SPIEN. Proponuję się lepiej zapoznać z tematyką fuse bitów, gdyż są to podstawy przy starciu z mikrokontrolerami.

    Dodatkowo, to co jest generowane na dole na podanej przeze mnie stronie, to tylko komendy powodujące zapisanie fues bitów, do tego należy dołączyć jeszcze konfigurację: port do którego podpięty jest programator, następnie typ programatora oraz oczywiście model procesora, który programujemy.

    Myślę, że dobrym początkiem byłoby skorzystanie z nakładki Burn-O-Mat połączone z poszerzeniem wiedzy na temat fuse bitów.
REKLAMA