Mikrokontrolery AVR część 7 – tmier1

W poprzednim artykule zajmowaliśmy się timerem 0, który był stosunkowo prostym układem, w tej część będzie zawierała opis timera 1. Rysunek poniżej pomoże bardzo w zrozumieniu działania licznika, jednak co do szczegółów odsyłam do noty katalogowej, bo to zagadnienie jest z byt szerokie jak na ten artykuł. Postaram się jednak opisać podstawowe tryby pracy tego licznika.

Jest to o wiele bardziej rozbudowany układ, mogący pracować w kilku (15) trybach. Mamy takie tryby jak PWM, CTC, oraz tryb normalny. Tryby PWM i CTC mają jeszcze po kilka odmian, ale to tym za chwile.

Tryb normalny, to taki prosty licznik, jak licznik0, czyli zlicza aż się przepełni o wtedy daje sygnał przerwania. Łatwe i proste.

Tryb PWM zajmuje się generacją przebiegu prostokątnego o regulowanym współczynniku wypełnienia. Mamy takie tryby PWM:

  • szybki PWM
  • PWM z poprawną fazą
  • PWM z poprawną fazą i częstotliwością

Tryb szybki PWM (fast PWM)

Jego zadaniem jest generowanie sygnału o zmodulowanym współczynniku wypełnienia na wyjściach OC1A i OC1B. Zlicza od zera, aż do momentu porównania z rejestrem OCR1A lub OCR1B, chyba, że wcześniej osiągnie wartość określoną jako TOP. Kiedy zostanie osiągnięta odpowiednia wartość, stan na liniach OC1A i OC1B zmienia swój stan w sposób określony poprzez bity COM1A1:0. Tryb ten charakteryzuje się wysoką częstotliwością generowanego sygnału. A o tej częstotliwości mówi ustawienie preskalera, i obliczamy ją ze wzoru:

Działa to tak, licznik zlicza zawsze w górę, kiedy osiąga wartość równą zawartości rejestru OCR1x stan na wyjściu OC1x zostanie ustawiony na stan logiczny 0, a gdy licznik się przepełnia i zaczyna zliczać od nowa, to wtedy na wyjściu OC1x ustawia się logiczna 1. Świetnie to obrazuje wykres zaczerpnięty z noty katalogowej.

Radzę go bardzo dokładnie przestudiować, gdyż zrozumienie tego wykresu stanowi klucz do programowania timera1 w kontrolerach AVR.

Pojawia się na tym wykresie zanegowanie linii OCnx, jest możliwe osiągnięcie takiego efektu poprzez odpowiednie bity rejestru TCCR1A. Te bity to COM1A0, COM1B0, COM1A1 oraz COM1B1. Poprzez odpowiednią konfiguracje tych bitów możemy ustawić tak zmiany stanów logicznych na wyjściach licznika.

PWM z poprawną fazą

Różnica pomiędzy tym trybem a poprzednim jest taka, że zlicza on najpierw w górę, a następnie w dół. Co zapewnia poprawną fazę generowanego sygnału. Częstotliwość sygnału, który zostanie wygenerowany w tym trybie można obliczyć z tego samego wzory, co przy trybie szybkiego PWM.Ten powyższy schemat pokazuję jak działa licznik w tym trybie. Ze względu na to że licznik zlicza w dwie strony jest on zalecany do sterowania silnikami.

Tryb CTC

W tym trybie licznik zlicza w górę, aż do momentu porównania z rejestrem OCR1A lub ICR1. W chwili gdy zachodzi zrównanie się zawartości licznika z rejestrem OCR1A bądź ICR1 (zależnie od trybu) stan licznika zostaje wyzerowany, a stan na linii OC1A ulega zmianie na przeciwny.

Ten tryb umożliwia generowanie przebiegu prostokątnego o określonej częstotliwości, która jest zależna od zawartości rejestru OCR1A lub ICR1. A policzenie tej częstotliwości umożliwia wzór:

Gdzie N to wartość prescalera.

Wybór trybu

Do wyboru trybu służą bity WGM10, WGM11 z rejestru TCCR1A oraz bity WGM12, WGM13 z rejestru TCCR1B. Konfigurację trybów opisuje tabla poniżej.

Trybów jest oczywiści o wiele więcej niż te co opisywałem, jednak nie ma miejsca w tym artykule na tak szeroki opis. Zachęcam do studiowania noty katalogowej kontrolerów AVR, tam jest wszystko zawarte.

Mode WGM13 WGM12 WGM11 WGM10 Timer/Counter Mode TOP Update of OCR1x TOV1 Flag Set on
0 0 0 0 0 Normal 0xFFFF Immediate MAX
1 0 0 0 1 PWM, Phase Correct, 8-bit 0x00FF TOP BOTTOM
2 0 0 1 0 PWM, Phase Correct, 9-bit 0x01FF TOP BOTTOM
3 0 0 1 1 PWM, Phase Correct, 10-bit 0x03FF TOP BOTTOM
4 0 1 0 0 CTC OCR1A Immediate MAX
5 0 1 0 1 Fast PWM, 8-bit 0x00FF BOTTOM TOP
6 0 1 1 0 Fast PWM, 9-bit 0x01FF BOTTOM TOP
7 0 1 1 1 Fast PWM, 10-bit 0x03FF BOTTOM TOP
8 1 0 0 0 PWM, Phase and Frequency Correct ICR1 BOTTOM BOTTOM
9 1 0 0 1 PWM, Phase and Frequency Correct OCR1A BOTTOM BOTTOM
10 1 0 1 0 PWM, Phase Correct ICR1 TOP BOTTOM
11 1 0 1 1 PWM, Phase Correct OCR1A TOP BOTTOM
12 1 1 0 0 CTC ICR1 Immediate MAX
13 1 1 0 1 (Reserved)
14 1 1 1 0 Fast PWM ICR1 BOTTOM TOP
15 1 1 1 1 Fast PWM OCR1A BOTTOM TOP

Przykłady

Dla tych co nic nie zrozumieli z tego artykułu (może ich być sporo) teraz kilka przykładów, które mam nadzieje rozwieją nie domówienia.

Przykład 1

Ten przykład będzie pokazywał działanie licznika w trybie CTC. Jego zadaniem będzie wygenerować przebieg prostokątny o o określonej częstotliwości. Będziemy korzystać z trybu numer 4.

#define F_CPU 1000000 //ustawienie oscylatora na 1MHz
#include <avr/io.h> //dołączenie podstawowej biblioteki

int main()
{
     TCCR1B |= (1<<WGM12); //włączenie trybu CTC
     TCCR1B |= (1<<CS10) | (1<<CS11); //ustawienie preskalera na 64
     OCR1A = 1000; //wartość do której zlicza licznik
     while(1) //pusta pętla
     {

     }
}

Ten program będzie powodował generowanie przebiegu prostokątnego o częstotliwości około 7,8Hz. Czyli jak by podłączyć diodę LED do wyjścia OC1A to będzie jeszcze widać jak miga. Oczywiście diodą podpinamy poprzez rezystor ograniczający.

Przykład 2

Teraz zajmiemy się trybem PWM. Najczęściej spotkany jest tryb szybki, więc i taki przykład przedstawię. Będziemy mieli 10 bitową rozdzielczość, czyli tryb 7.

#define F_CPU 1000000 //ustawienie oscylatora na 1MHz
#include <avr/io.h> //dołączenie podstawowej biblioteki

int main()
{
     TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<WGM10)|(1<<WGM11);
     //konfiguracja trybu
     TCCR1B = (1<<CS10)|(1<<WGM12);
     //konfiguracja trybu i prescalera
     OCR1A = 500;
     //wartość określająca współczynnik wypełnienia

     while(1) //pusta pętla
     {

     }
}

Ten program generuje sygnał PWM o wypełnieniu niecałe 50%. Wartość dla OCR1A może wynosić od 0 (wypełnienie 0%) do 1023 (wypełnienie 100%).

Przykłady przedstawione w artykule nie były w żaden sposób sprawdzane, więc nie mogę zagwarantować bezproblemowego ich działania. Jednak w założeniach teoretycznych są prawidłowe.

Na tym przykładzie zakończę ten opis timera 1 w mikrokontrolerach AVR. Jest to tylko mała cześć możliwości tego licznika. Zachęcam to przestudiowania go głębiej, bo jest bardzo przydatnym narzędziem.

W następnej części przedstawię ostatni z liczników czyli licznik/czasomierz 2.

Komentarze do „Mikrokontrolery AVR część 7 – tmier1

  1. Witam,
    w pierwszym kodzie po
    OCR1A = 1000 powinien być średnik
    i w while wartość np. 1
    PS. bardzo porządne artykuły, dobra robota
    Pozdrawiam

  2. Przykład 2, żeby działała dioda trzeba jeszcze dodać:

    DDRB = _BV(PB1);

    Trochę mi zeszło żeby dowiedzieć się czemu nie działa 🙂

  3. czy wykorzystując PWM da się ustawić jego wyjście na OC1B, lub włączyć jednocześnie dwa niezależne PWN – jedno z wyjściem na OC1A, drugie na OC1B?

  4. Proszę sprawdzić poprawność wzoru na wyliczenie częstotliwości dla licznika ustawionego w tryb fast PWM.
    Nie nie powinien on wyglądać w ten sposób: focnxpwm = fclk_io/N*(1+TOP).

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.