Timer Interrupt beim Attiny45/85

Der Attiny45/85 besitzt 2 8-Bit Timer, Timer0 und Timer1, die zum Teil in Arduino-Funktionen und/oder zum Teil in Libraries bereits in Verwendung sind. Ein Überschreiben von Timer-Register kann also zu Komplikationen führen und sollte mit Vorsicht angewendet werden. So scheinen die Funktionen delay(), millis() und micros() den Timer0 zu verwenden.


Nachfolgend zeige ich am Beispiel des Timer1 die Auslösung eines zeitgesteuerten Interrupts im "Clear Timer on Compare Mode" (CTC-Mode). Die Vorgangsweise kann prinzipiell auch auf den Timer0 angewendet werden, Unterschiede zwischen den Timern sind dem Datenblatt des Attiny45/85 zu entnehmen.


Verwendete Register:

  • Status Register: SREG
  • Timer/Counter1: TCNT1
  • Timer/Counter1 Control Register: TCCR1
  • Timer/Counter1 Output Compare Register C: OCR1C
  • Timer/Counter Interrupt Mask Register: TIMSK


Vorgangsweise:

Der Modus muss im TCCR1-Register auf CTC-Mode (Clear Timer on Compare Mode) eingestellt werden.

Der Inhalt des 8-Bit TCNT1-Register wird mit dem - um den Faktor des Vorteilers (Prescaler) verminderten - Systemtakt erhöht und mit dem Inhalt des 8-Bit OCR1C-Registers verglichen. Bei Übereinstimmung wird, sofern das entsprechende Maskier-Bit im TIMSK-Register und das globale Interrupt-Enable-Bit gesetzt sind, ein Interrupt ausgelöst.


Vorteiler und Vergleichswert (Inhalt des OCR1A-Register) ermitteln:

Vorgaben (beispielhaft):

  • CPU-Frequenz Attiny: 8.000.000 Hz

  • Gewünschte Interruptfrequenz: z.B. 50 Hz (= 20 ms Periodendauer)

  • Mögliche Vorteiler: 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 und 163481

Der Vergleichswert kann mit folgender Formel ermittelt werden:

Mit gewähltem Vorteiler von 1024 ergibt sich:

Vergleichswert = (8.000.000 / (1024 * 50)) - 1 = 155,25 -> gerundet 155!

Da der Vergleichswert in das 8-Bit Register OCR1C geschrieben wird, darf der Vergleichswert maximal 255 betragen. Hat die Berechnung einen höheren Wert ergeben, so ist ein gößerer Wert für den Vorteiler in die Formel einzusetzen, bis der Vergleichswert kleiner oder gleich 255 ist!

Ist der Vergleichswert auch bei Verwendung des größten Vorteiles noch immer größer als 255, kann man z.B. den Vergleichswert für die doppelte Interruptfrequenz ermitteln und - sofern dann der Vergleichswert kleiner gleich 255 ist - die erforderliche Aktion nur bei jedem zweiten Aufruf der Interrupt-Serviceroutine durchführen. Realisiert kann das z.B. mit einem als "static"-deklarierten Zähler in der Service-Routine erfolgen:

ISR(TIMER1_COMPA_vect)
{
  static byte zaehler = 0;
  if (zaehler == 1)
  {
    // Interrupt-Aktion
    .......
    //
    zaehler = 0;
  }
  else zaehler++;
}


Hier nun zusammengefasst, wie die Register gesetzt werden müssen:

Löschen des globales Interrupt-Enable-Bit:

cli();

oder

SREG &= 0x7F;


Status Register - SREG:



CTC-Mode aktivieren:

TCCR1 = 0; //Löschen des TCCR1-Registers

TCCR1 |= (1 << CTC1);  //Setze CTC-Mode


Timer/Counter 1 Control Register - TCCR1:



Vorteiler (Prescaler) definieren:

(Im Beispiel ist der Vorteiler 1024)

Der Vorteiler ist in das TCCR1-Register in die Clock Select Bits CS13-CS10 (Bits 3-0) einzutragen.

TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);


TCCR1 - Timer/Counter Control Register:


Die Bitkombination der Clock Select Bits für den gewünschten Vorteiler ist in nachfolgender Tabelle ersichtlich:

             


Timer/Counter1 Register - TCNT1 löschen:

TCNT1 = 0;  //Timer Counter Register löschen


Timer/Counter1 Output Compare Register C - OCR1C setzen:

OCR1C = 155; //Setzen des ermittelten Vergleichswertes


Timer/Counter Interrupt Mask Register setzen:

TIMSK |= (1 << OCIE1A); //Bit Output Compare A Match Interrupt Enable


Timer/Counter Interrupt Mask Register - TIMSK:



Setzen des globales Interrupt-Enable-Bit:

sei();

oder

SREG |= 0x80;


Status Register - SREG:


Wird nun ein Timer1-Interrupt ausgelöst, springt der Programmablauf eine zu erstellende Interrupt-Serviceroutine "ISR(TIMER1_COMPA_vect)".

Der Name der Interrupt-Serviceroutine ist vom System fix vorgegeben und darf nicht verändert werden!


Wie man einen Attiny mit Hilfe eines Arduino programmiert und den Bootloader für eine Taktfrequenz von 8 MHz installiert, findet ihr hier: Attiny programmieren


Programmbeispiel für Timer1-Interrupt siehe: Modellbahnschranke