Timerji v Arduino Uno (Atmega 328P)

Timerji so srce avtomatizacije. Omogočajo nam nadzor ne le nad tem kaj se zgodi temveč kaj se dogaja. Omogočajo nam nadzor nad časom.

Timerji (časovniki) ali bolj natančno timerji (časovniki) / števci so del strojne opreme, vgrajene v Arduino Uno. Z njimi lahko merimo časovne dogodke, lahko pa z njimi štejemo impulze.

Arduino Uno vsebuje mikrokontroler ATmega 328P. Vsebuje tri timerje, Timer0, Timer1 in Timer2. Timer0 in Timer2 sta 8-bitna, Timer1 pa je 16-bitni. Osnovna razlika med 8-bitnim in 16-bitnim je resolucija. 8-bitni ima resolucijo 255, 16-bitni pa 65535.

Vsi timerji so odvisni strojne ure. Arduino Uno poganja strojna ura (oscilator) frekvence 16 MHz. Privzeto so v Arduino nastavljeni (konfigurirani) vsi timerji na frekvenco 1 KHz, privzeto pa so omogočene tudi prekinitve (interrupts).

Timer0:

Timer0 je v Arduino namenjen časovni funkciji kot so zakasnitve delay(), millis() in micros(). Zato moramo paziti pri uporabi tega timerja, saj s spremenjenimi nastavitvami spremenimo tudi časovne funkcije.

Deluje z večimi registri. Registri Timer/Counter0 (TCNT0) register in Output Compare Registra (OCR0A in OCR0B) so 8-bitni. TCNT0 register se povečuje za 1 ob vsakem strojnem ciklu. Njegova maksimalna vrednost je lahko 255, ko jo doseže, se začne povečevati zopet od 0. Pri tem setira (postavi na 1) zastavico TOV0 (Timer overflow) v registru TIFR (Timer interrupt flag register). Pri 16 MHz strojni uri se Timer0 register TCNT0 poveča za 1 vsake 0,0625 µs.

t = 1/16000000 = 0,0625 µs

Slika 1: Register TCNT0 (vanj lahko pišemo ali iz njega beremo R/W)

Oba Output Compare Registra (OCR0A in OCR0B) ves čas primerjata vrednost timerjevega registra TCNT0. Razultat tega primerjanja lahko uporabimo za generiranje izhodnih impulzov (signalov), ki so lahko pulzno širinski (PWM) ali impulzi različnih frekvenc na izhodnih (Output Compare pins) pinih OC0A in OC0B. Ta dva pina sta pri Arduino Uno pin 6 (OC0A) in pin 5 (OC0B). Ko timer doseže nastavljeni vrednosti OCR0A in OCR0B (vrednosti zapišemo v ta dva registra), setira (postavi na 1) zastavici Compare Flag (OCF0A oziroma OCF0B, ki se nahajata v registru TIFR), kar lahko izkoristimo za proženje Output Compare prekinitev.

S Timer0 lahko prožimo tri med seboj neodvisne prekinitve (TOV0, OCF0A in OCF0B).

Slika 2: Register OCR0A (vanj lahko pišemo ali iz njega beremo R/W)

Slika 3: Register OCR0B (vanj lahko pišemo ali iz njega beremo R/W)

Timer0 lahko povečuje svojo vrednost s strojno uro, lahko pa uporabimo preddelilnik, ki deli prožilne impulze (impulze strojne ure). Preddelitev nastavljamo s prvimi tremi biti (CS00, CS01 in CS02) registra Timer/Counter Control Register (TCCR0B).

Slika 4: Register TCCR0B (Timer/Counter Control register)

Slika 5: Register TCCR0A (Timer/Counter Control register)

Tabela 1: Vloga bitov CS02, CS01 in CS00 v registru TCCR0B.

Tabela 2: Različni načini delovanja Timer0.

Mode 0, Normal:

Normalni način delovanja smo že opisali. V tem načinu se Timer0 (register TCNT0) enostavno povečuje od 0x00 do 0xFF (od 0 do 255). Ko preseže svojo vrednost se začne povečevati zopet od 0. Normalno delovanje (Normal) smo spoznali pri krmiljenju zapornic na železniškem prehodu in sicer smo uporabili Timer2, ki je tudi 8-bitni.

Mode3, Fast PWM:

Slika 6: Prikaz delovanja v načinu Fast PWM

Fast PWM imenujemo, ker lahko generiramo pulzno širinske signale visokih frekvenc. Timer povečuje svojo vrednost od 0 do 255. V registra OCR0A in OCR0B lahko zapišemo vrednosti od 0 do 255. Ko timer doseže vrednost, zapisano v OCR0A, na pinu 6 (OC0A) preklopi logično stanje iz 1 na 0. Ko doseže vrednost, zapisano v OCR0B, na pinu 5 (OC0B) preklopi logično stanje iz 1 na 0. Kadar pa pride na timerju do prekoračitve svoje vrednosti (ovwrflow), na obeh pinih preklopi logično stanje iz 0 na 1.

Primer:

/*

   Primer Fast PWM, Timer0

   April 2015

   Avtor: Milan Ivič

 */

 void setup()

 {

  pinMode(5, OUTPUT);      //Timer0 (OCR0B)

  pinMode(6, OUTPUT);      //Timer0 (OCR0A)

 }

 void loop()

 {

 /*

  Timer0 (8-bitni), Fast PMW:

  TCCR0A = _BV(COM0B1)  => Setiranje bita COM0B1, pin 5 PWM

  TCCR0A = _BV(COM0A1)  => Setiranje bita COM0A1, pin 6 PWM

  TCCR0A = _BV(WGM00) | _BV(WGM01) => Set bita WGM00 in bita WGM01, Fast PWM (mode 3)

  TCCR0B = _BV(CS00) | _BV(CS02) => Setiranje bita CS00 in bita CS02, preddelitev 1:1024

  f = 16 MHz/(1024*256) = 61,035 Hz

  */

  TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);

  TCCR0B = _BV(CS00) | _BV(CS02);

  OCR0A = 220;                      //pin 6    Duty Cycle = (220 + 1)/(256) = 86,3 %

  OCR0B = 30;                        //pin 5   Duty Cycle = (30 + 1)/(256) = 12,1 %

  //Pri Fast PWM potrebuje timer za dosego zg. meje 1 cikel več od primerjalne vrednosti.

  }

Slika 7: Prikaz PWM signalov (pin 6 zgoraj, pin 5 spodaj).

Mode7, Fast PWM:

Pri načinu Fast PWM imamo možnost nastavitve Top vrednosti z registrom OCR0A (mode 7, glej tabelo 2). Ta način omogoča večji nadzor nad izhodno frekvenco PWM signala. Timer0 v tem primeru povečuje svojo vrednost od 0 do vrednosti, ki jo zapišemo v register OCR0A in ne do 255. Z nižanjem vrednosti OCR0A višamo frekvenco. PWM lahko v tem primeru določamo samo na izhodu OC0B, saj je z OCR0A nastavljena zgornja (Top) vrednost in ima izhod OC0A (pin 6) fiksni duty cycle 50 %.

Slika 8: Prikaz delovanja v načinu Fast PWM, mode 7

Primer:

Frekvenco PWM signala na pinu 5 (OC0B) je: fPWM = 16 MHz / ((160+1)*64) = 1,55 kHz.

Frekvenco PWM signala na pinu 6 (OC0A) je: fPWM = 16 MHz / ((40+1)*64*2) = 776,4 Hz.

Duty cycle na pinu 5 (OC0B) = (40+1) / (160+1) *100 % = 25,5 %

V tem primeru Timer0 povečuje svojo vrednost od 0 do 160. Ko doseže vrednost 160 v naslednjem strojnem ciklu preklopi stanje na OC0A in OC0B (zato 160+1).

/*

   Primer Fast PWM, mode 7, Timer0

   April 2015

   Avtor: Milan Ivič

 */

 void setup()

 {

   pinMode(5, OUTPUT);      //Timer0 (OCR0B)

   pinMode(6, OUTPUT);      //Timer0 (OCR0A)

 }

 

void loop()

 {

 /* 

  Timer0 se povečuje do vrednosti OCR0A, ki jo lahko spreminjamo in s tem spreminjamo frekvenco.

  Na izhodu OC0A (pin 6) je v tem primeru fiksni duty cycle 50 %.

 

  TCCR0A = _BV(COM0B1)  => pin 5 PWM

  TCCR0A = _BV(COM0A0)  => ker je WGM02 =1: OCR0A compare, pin 6 PWM, fiksni duty cycle 50 %

  TCCR0A = _BV(WGM00) | _BV(WGM02)

  TCCR0B = _BV(WGM02) | _BV(CS00) | _(CS01) => (Fast PWM, Top OCR0A, mode 7), preddelitev 64

  f pin5 (izhod OC0B) = 16 MHz/(64*(160+1)) = 1,55 kHz

  fpin6 (izhod OC0A) = 16 MHz/(64*(160+1)*2) = 776,4 Hz

 */

 TCCR0A = _BV(COM0A0) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);

 TCCR0B = _BV(WGM02) | _BV(CS00) | _BV(CS01);

 OCR0A = 160;                                                //Duty cycle = 50%

 OCR0B = 40;                                                 //Duty cycle = (40+1)/(160+1) = 25,5%

 }

Slika 9: Prikaz PWM signalov (pin 6 zgoraj, pin 5 spodaj)

Mode 1, PWM Phase Correct:

Slika 10: Prikaz delovanja v načinu Fhase Correct PWM, mode 1

Timer0 povečuje svojo vrednost od 0 do 255. Ko jo doseže, se začne njegova vrednost zmanjševati od 255 do 0. Stanje na izhodnih pinih 5 (OC0B) in 6 (OC0A) se postavi na 0, ko Timer0 pri povečevanju svoje vrednosti doseže vrednost OCR0B oziroma OCR0A in se postavi na 1, ko Timer0 pri zmanjševanju svoje vrednosti doseže vrednost OCR0B oziroma OCR0A.

Vrednost Top (tabela 2) je določena 0xFF (FF(16) = 255(10) = 11111111(2))

Primer:

 /*

   Primer Phase Correct PWM, mode 1, Timer0

   April 2015

   Avtor: Milan Ivič

 */

 void setup()

 {

   pinMode(5, OUTPUT);      //Timer0 (OCR0B)

   pinMode(6, OUTPUT);      //Timer0 (OCR0A)

 }

 

 void loop()

 {

 /*

  Timer0 (8-bitni), Phase correct PMW:

  TCCR0A = _BV(COM0B1)  => Setiranje bita COM2B1, pin 5 PWM

  TCCR0A = _BV(COM0A1)  => Setiranje bita COM2A1, pin 6 PWM

  TCCR0A = _BV(WGM00)   => Set bita WGM00, Phase correct PWM (mode 1)

  TCCR0B = _BV(CS00) => Setiranje bita CS00, preddelitev 1:1

  f = 16 MHz/(2*1*255) = 31,37 kHz

 */

  TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);  

  TCCR0B = _BV(CS00);        //Preddelitev 1

  OCR0A = 200;               //pin 6 => Duty Cycle = 200/255 = 78,4 %

  OCR0B = 50;                //pin 5 => Duty Cycle = 50/255 = 19,6 %

 }

Slika 11: Prikaz PWM signalov (pin 6 zgoraj, pin 5 spodaj)

Mode 5, PWM Phase Correct:

Slika 12: Prikaz delovanja v načinu Fhase Correct PWM, mode 5

V tem primeru Top vrednost določa vrednost, zapisana v registru OCR0A. Timer0 v tem primeru povečuje svojo vrednost od 0 do vrednosti, ki jo zapišemo v register OCR0A in ne do 255. Z nižanjem vrednosti OCR0A višamo frekvenco. PWM lahko v tem primeru določamo samo na izhodu OC0B, saj je z OCR0A nastavljena zgornja (Top) vrednost in ima izhod OC0A (pin 6) fiksni duty cycle 50 %.

Primer:

 /*

   Primer Phase Correct PWM, mode 5, Timer0

   April 2015

   Avtor: Milan Ivič

 */

 void setup()

 {

   pinMode(5, OUTPUT);      //Timer0 (OCR0B)

   pinMode(6, OUTPUT);      //Timer0 (OCR0A)

 }

 void loop()

 {

  /*

   Phase correct PWM, mode 5:

   Timer0 se povečuje do vrednosti OCR0A in nato zmanjšuje vrednost od OCR0A do 0.

   Vrednost OCR0A lahko spreminjamo in s tem spreminjamo frekvenco.

   Na izhodu OC0A (pin 6) je v tem primeru fiksni duty cycle 50 %.

   TCCR0A = _BV(COM0B1)  => pin 5 PWM

   TCCR0A = _BV(COM0A0)  => ker je WGM02 =1: OCR0A compare, pin 6 PWM, fiksni duty cycle 50%

   WGM00 in WGM02 sta 1 => PWM Phase correct, Top = OCR0A (mode 5)

   f pin5(izhod B) = 16 MHz/(256*160*2) = 195,3 Hz

   fpin6(izhod A) = 16 MHz/(256*160*2*2) = 97,6 Hz

  */

  TCCR0A = _BV(COM0A0) | _BV(COM0B1) | _BV(WGM00);

  TCCR0B = _BV(WGM02) | _BV(CS02);              //(CS02 = 1) => Preddelitev 1:256

  OCR0A = 160;                  //Duty cycle = 50 %

  OCR0B = 40;                    //Duty cycle = 40/160 = 25 %

 }

Slika 13: Prikaz PWM signalov (pin 6 zgoraj, pin 5 spodaj)

Mode 2, CTC (Clear Timer on Compare match)

Ko doseže Timer0 s svojim registrom TCNT0 Top vrednost, zapisano v OCR0A se postavi na 0 od koder se začne ponovno povečevati. Ob tem sproži prekinitev, če smo jo omogočili. Omogočimo jo lahko s postavitvijo bita OCIE0 (Output Compare Interrupt Enable 0) v registru TIMSK0 (Timer/Counter Interrupt Mask Register).

Slika 14: Register TIMSK0 (Timer/Counter Interrupt Mask Register)

Slika 15: Register TIFR0 (Timer/Counter Interrupt Flag Register)

Nastaviti (konfigurirati) želimo potrebne registre, da bo program v CTC načinu vsake 2 ms skočil v prekinitveno rutino, v kateri bo preklopil LED diodo. Timer0 je 8-bitni, njegova vrednost je lahko največ 255. Arduino Uno vsebuje 16 MHz kristalni oscilator. Zanima nas resolucija časovnika Timer0.

Resolucija Timer0 = 1/16 MHz = 0,0625 µs. Brez preddelilnike bi se napolnil na največjo vrednost (255) v cca 16 µs. Zato moramo za naš primer uporabiti preddelilnik. Uporabili bomo preddelitev 1:1024. Timerjeva resolucija bo sedaj 0,0000000625 s * 1024 = 0,000064 s.

Koliko strojnih ciklov bo sedaj potreboval Timer0, da bo sprožil prekinitev (da doseže vrednost OCR0A) vsake 2 ms?

2 ms = (Timer0 resolucija) * (Število strojnih ciklov + 1)

(Število strojnih ciklov + 1) = 2 ms / (Timer0 resolucija)

(Število strojnih ciklov + 1) = 2 ms / 0,064 ms

Število strojnih ciklov = 31,25 - 1

Število strojnih ciklov = 30

Program bo vsake 2 ms skočil v prekinitveno rutino. V prekinitveni rutini bo vklopil LED diodo, čez 2 ms jo bo izklopil itd. Periodni čas preklapljanja LED diode bo torej znašal 4 ms (2 ms LED sveti, 2 ms LED ne sveti).

Frekvenca utripanja LED diode bo znašala fLED = 1/4 ms = 250 Hz.

/*

   Primer CTC, mode 2, Timer0

   April 2015

   Avtor: Milan Ivič

 */

 void setup()

 {

   pinMode(7, OUTPUT);

 

   noInterrupts();                  //Onemogočimo prekinitve

   TCCR0A = 0;                      //Inicializacija TCCR0A registra na 0

   TCCR0B = 0;

   TCNT0  = 0;                       //Inicializacija timerjevega registra na 0

   TCCR0A = _BV(WGM01);                 //CTC => mode 2

   TCCR0B = _BV(CS02) | _BV(CS00);     //(CS02 in CS00 sta 1) => Preddelitev 1:1024

   OCR0A = 30;                          //Nastavitev vrednosti Top vrednosti

   TIMSK0 = _BV(OCIE0A);                //Omogočimo prekinitve na CTC, ko timer doseže Top (OCR0A)

   interrupts();                        //Omogočimo prekinitve

 

   /*  

    Zanima nas, koliko strojnih ciklov potrebuje timer v CTC mode, da sproži prekinitev (da doseže

    vrednost OCR0A) vsake 2 ms.

    2 ms = (Timer0 resolucija) * (število strojnih ciklov + 1)

    (število strojnih ciklov + 1) = 2 ms / (0,000064 s)    

    (število strojnih ciklov + 1) = 31,25

    število strojnih ciklov = 30

    V register OCR0A zapišemo 30. Prekinitev se bo sprožila vsake 2 ms.

  */

 }

 void loop()

 {

 

 }

 ISR(TIMER0_COMPA_vect)    //Prekinitvena rutina

 {

    digitalWrite(7, ! digitalRead(7));

 }

Slika 16: Prikaz signala na pinu 7, kamor je priključena LED dioda

Tabela 3 (zgoraj): Različni načini delovanja Timer1

Tabela 4 (zgoraj): Vloga bitov CS12, CS11 in CS10 v registru TCCR1B.


Timer1:

Timer1 uporablja v Arduino knjižnico za servo motorčke. Je 16-bitni, njegova največja vrednost jo lahko 0xFFFF oziroma 65535. PWM izhoda časovnika Timer1 v Arduino Uno sta pin 9 (OC1A) in pin 10 (OC1B).

S Timer1 lahko prožimo štiri med seboj neodvisne prekinitve (TOV1, OCF1A, OCF1B in ICF1).

Slika 17: Register TCCR1A (Timer/Counter1 Control Register A)

Slika 18: Register TCCR1A (Timer/Counter1 Control Register B)

Slika 19: Register TIMSK1 (Timer/Counter1 Interrupt Mask Register)

Slika 19: Register TIMSK1 (Timer/Counter1 Interrupt Mask Register):

Slika 20: Register TIFR1 (Timer/Counter1 Interrupt Flag Register)

Mode 14, Fast PWM, Top ICR1:

Primer:

  /*

   Primer Fast PWM, Top ICR1, mode 14, Timer1

   April 2015

   Avtor: Milan Ivič

 */

 void setup()

 {

   pinMode(9, OUTPUT);       //Timer1

   pinMode(10, OUTPUT);      //Timer1

 }

 void loop()

 { 

  TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11);      //Vključitev pinov (9, 10)

  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);       //Fast PWM, Mode 14 (tabela), preddelitev 1:1

  ICR1 = 59999;                 //Frekvenca: f=(16*10^6)/(1*(1+59999)) = 266,6 Hz

  OCR1A = 4000;                 //Duty cycle = 4000/59999*100 % = 6,7 (pin 9, OC1A)

  OCR1B = 24000;                //Duty cycle = 24000/59999*100 % = 40 % (pin 10, OC1B)

 }

Slika 21: Prikaz PWM signalov (pin 9 zgoraj, pin 10 spodaj)

Primer:

Želimo generirati PWM signal s frekvenco 2500 Hz in Duty cycle 40 %. PWM signal želimo na pinu 9.

/*

   Primer Phase and Frequency Correct, Top ICR1, mode 8, Timer1

   April 2015

   Avtor: Milan Ivič

 */

 void setup()

 {

  pinMode(9, OUTPUT);      //Timer1, pin 9 (OC1A)

 }

 void loop()

 {

  TCCR1A = _BV(COM1A1);               //Vključitev pina 9

  TCCR1B = _BV(WGM13) | _BV(CS10);    //Phase and Frequency Correct PWM mode 8, preddelitev 1:1

  ICR1 = 3200;                        //Frekvenca: f=(16*10^6)/(2*1*3200) = 2500 Hz

  OCR1A = 1280;                       //Duty cycle = 1280/3200 => = 40 %

 }

Slika 22: Prikaz PWM signala na pinu 9

Primer:

Register TIMSK1 (Timer/Counter1 Interrupt Mask Register) kontrolira, katero prekinitev lahko Timer1 proži. S setiranjem bita TOIE1 (Timer1 Overflow Interrupt Enable) smo mu povedali, naj proži prekinitev, ko Timer1 prekorači svojo vrednost. S setiranjem bita CS10 zaženemo Timer1 in ko pride do overflow-a bo sprožil prekinitev - poklical prekinitveno rutino ISR(TIMER1_OVF_vect). To bo storil vsakič, ko pride do prekoračitve timerjeve vrednosti.

V prekinitveni rutini bomo preklapljali LED diodo, priključeno na pin 7.

Pri 16 MHz oscilatorju traja en strojni cikel 1/(16* 10^6) sekund, kar znaša 0,0625 µs. To pomeni, da bo Timer1, ki je 16-bitni dosegel maksimalno vrednost v času 65535*0,0625 µs = 4,1 ms. Prekinitev bo sprožal vsakih 4,1 ms. Ta čas je prekratek, da bi videli utripanje LED diode. Zato uporabimo preddelilnik, ki deli strojne cikle, namenjene timerju. S setiranjem bita CS10 in CS12 določimo preddelitev 1:1024. Timerjeva resolucija povečevanja svoje vrednosti v tem primeru znaša: 1/(16* 10^6/1024) = 0,000064 sekunde oziroma 0,064 ms. Z uporabo preddelilnika 1:1024 bo timer dosegel maksimalno vrednost: 0,064 ms * 65535 = 4,19424 sekunde. Vsake cca. 4,2 sekunde bo sprožil prekinitev.

Če izberemo preddelitev 1:256 (setiramo bit CS12), bo Timer1 sprožil prekinitev vsake 1/(16* 10^6/256) = 1,04856 sekunde.

Do kakšne vrednosti bi se moral povečevati Timer1, da bi sprožil prekinitev vsako sekundo?

x = 65535/1,04856 = 62500.

Timerjeva vrednost je torej za 65535 - 62500 = 3035 prevelika. Ena od možnosti je ta, da določimo začetno vrednost za Timer1, ki bo znašala 3035 in se bo začel povečevati od te vrednosti naprej. To vrednost bi zapisali v timerjev register TCNT1. Ko bo Timer1 sprožil prekinitev, se bo v prekinitveni rutini vklopila LED dioda ki bo svetila, dokler se v naslenji prekinitvi, torej čez 1 sekundo, ne bo izklopila. Frekvenca utripanja LED diode bo v tem primeru 0,5 Hz (1 s LED sveti, 1 s LED ne sveti).

Če želimo frekvenco utripanja LED diode spremeniti na 1 Hz (0,5 s LED sveti, 0,5 s LED na sveti), moramo spremeniti začetno vrednost registra TCNT1:

Do kakšne vrednosti bi se moral povečevati Timer1, da bi sprožil prekinitev vsake pol sekunde?

x = 65535/(2*1,04856) = 31250

Timerjeva vrednost je torej za 65535 - 31250 = 34285 prevelika. Zato v timerjev register TCNT1 zapišemo to vrednost kot začetno.

V prekinitveni rutini moramo ponovno zapisati začetno vrednost registra TCNT1, v nasprotnem primeru bo Timer1 začel povečevati svojo vrednost od 0. Paziti moramo tudi, da pravilno napišemo ime prekinitvene rutine ISR(TIMER1_OVF_vect).  TIMER1 moramo pisati z velikimi črkami!

/*

   Primer overflow proženja prekinitev na  Timer1

   April 2015

   Avtor: Milan Ivič

 */

 int LED=7;

 void setup()

 {

  pinMode(LED, OUTPUT);

  noInterrupts();               //Onemogočimo prekinitve.

  TCNT1 = 0;                    //Inicializacija, vse bite registra postavimo na 0.

  TCCR1A = 0;                   //Inicializacija, vse bite registra postavimo na 0. 

  TCCR1B = 0;                   //Inicializacija, vse bite registra postavimo na 0.

  TIMSK1 = _BV(TOIE1);      //Omogočimo prekinitve na Timer1 overflow.

  TCNT1 = 34285;                //Začetna vrednost registra za proženje prekinitve vsake 0,5 sekunde.

  TCCR1B = _BV(CS12);       //Preddelilnik 1:256

  interrupts();                 //Dovolimo prekinitve.

 }

 void loop()

 {

   //Napišemo želeni program...

 }

 ISR(TIMER1_OVF_vect)            //Prekinitvena rutina.

 {

  digitalWrite(LED, ! digitalRead(LED));    //Preklop LED diode.

  TCNT1 = 34285;                             //Začetna vrednost registra za proženje prekinitve vsake 0,5 sekunde.

 }

Slika 23: Signal na pinu 7, utripanje LED diode s frekvenco 1 Hz

V zgornjem primeru smo uporabili normalno delovanje overflow prekinitev. Druga možnost je izbira CTC (Clear Timer to Compare Match). V tem primeru Timer1 primerja svojo vrednost z vrednostjo, ki jo nastavimo v registru OCR1A. Ko jo doseže, vklopi ustrezno zastavico (OCF1A) in sproži prekinitev, če smo jo dovolili. Dovolimo jo z vklopom (setiranjem) bita OCIE1A v registru TIMSK1.

Pri tej uporabi moramo imeti predstavo o tem, koliko strojnih ciklov bo potrebnih za interval 0,5 sekunde. Uporabimo preddelilnik 1:1024.

    Želeni čas = (timerjeva resolucija)  * (število timerjevih povečanj + 1)

    (število timerjevih povečanj + 1) = Želeni čas / (timerjeva resolucija)

    (število timerjevih povečanj + 1) = 0,5 s / 0,000064 s

    (število timerjevih povečanj + 1) = 7812,5

    število timerjevih povečanj = 7812,5 - 1 = 7811 (zaokrožimo)

Številu timerjevih povečanj smo prišteli 1 zato, ker timer potrebuje 1 korak za resetiranje na 0, ko doseže primerjalno vrednost.

/*

   Primer overflow proženja prekinitev na  Timer1

   April 2015

   Avtor: Milan Ivič

 */

 int LED=7;

 void setup()

 {

 pinMode(LED, OUTPUT);                         

 

 noInterrupts();                          //Onemogočimo prekinitve.

 TCCR1A = 0;                              //Inicializacija.

 TCCR1B = 0;                              //Inicializacija.

 TIMSK1 = _BV(OCIE1A);                    //Ko Timer1 doseže primerjalno (Compare) vrednost, sproži prekinitev.

 OCR1A = 7811;                            //Primerjalna vrednost, prekinitev vsake 0,5 s.

 TCCR1B = _BV(WGM12);                     //CTC, Mode 4.

 TCCR1B = _BV(CS12) | _BV(CS10);          //Preddelitev 1:1024.

 interrupts();         

 }

 void loop()

 {  

   //Napišemo želeni program...

 }

 ISR(TIMER1_COMPA_vect)

 {

  digitalWrite(LED, ! digitalRead(LED));

  TCNT1 = 0;                              //Inicializacija timerjevega registra TCNT1.

 }

Slika 24: Signal na pinu 7, utripanje LED diode s frekvenco 1 Hz