Pfad: Home ==> Mikrobeginner ==> 4. LED mit Timer     This page in English (external): Flag EN
ATtiny13

Lektion 4: Eine LED blinkt mit dem Timer


Mit dieser Lektion beenden wir die elendig langweiligen Schleifen und lassen die interne Timer-Hardware die langwierige Timing-Aufgabe vollautomatisch und exakt verrichten.

4.0 Übersicht

  1. Einführung in die Timer-Hardware
  2. Hardware, Bauteile, Aufbau
  3. Timer mit Standardeinstellungen
  4. Timer im CTC-Modus
  5. Timer im 128-kHz-Modus

4.1 Einführung in die Timer-Hardware

Der im Prozessor eingebaute Zähler (Timer/Counter, TC) ist die am häufigsten benutzte Hardwarekomponente. Der Timer wird auch bei späteren Lektionen zur Anwendung kommen, deshalb hier schon mal ein paar Anwendungen, um die LED auf verschiedene Arten blinken zu lassen.

Unterschiedliche AVR-Typen haben eine unterschiedliche Anzahl Zähler eingebaut. Diese sind mit Null beginnend durchnummeriert. Bei der Benennung von Timer-Ports beziehen sich 0, 1 oder 2 immer auf die Zählernummer. Der ATtiny13 hat nur einen Zähler, dennoch ist bei allen Portbenennungen eine Null eingefügt.

4.1.1 Timer

TCNT Timer in den AVR sind 8 oder 16 Bit breite Zähleinrichtungen. Sie zählen in der Regel aufwärts, bei 8 Bit Breite von 0 bis 255, bei 16 Bit Breite von 0 bis 65.535 und starten danach einfach wieder bei Null. Ihr Zählerstand ist im Port TCNT (8 Bit) bzw. in den beiden Ports TCNTH und TCNTL (16 Bit) zugänglich. Wird der Zählerport beschrieben, wird der Zähler auf diesen Stand gesetzt.

4.1.2 Timer-Impulsquellen

Die Möglichkeiten, mit denen der Zähler mit Impulsen versorgt werden kann, sind vielfältig. Mit dem Kontrollport B des 8-Bit-Timers, TCCRB, wird die Taktquelle des Timers ausgewählt. Multiplexer bedeutet "adressgesteuerter Umschalter". Drei Bits im Kontrollregister wählen damit die Signalquelle aus.

TCCRB

Acht verschiedene Quellen stehen zur Auswahl:
#BinZustandTaktung
0000AusKein Signal, Zählen abgeschaltet
1001TimerProzessortakt
2010TimerProzessortakt durch Acht
3011TimerProzessortakt durch 64
4100TimerProzessortakt durch 512
5101TimerProzessortakt durch 1.024
6110Counterexterner Anschluss T, fallende Flanken
7111Counterexterner Anschluss T, steigende Flanken

Mit den Zeilen

	ldi R16,1 ; R16 auf 1
	out TCCR0B,R16 ; in Kontrollport B

lässt sich der Timer mit dem Prozessortakt starten, mit

	clr R16 ; R16 auf Null
	out TCCR0B,R16 ; in Kontrollport B

wird der Timer wieder gestoppt. Mit der Instruktion "OUT" werden alle acht Bits des angegebenen Ports mit dem Inhalt des angegeben Registers beschrieben.

4.1.3 Timer und Compare-Match

Vergleicher Die ganze Timerei wäre nicht viel wert, wenn wir nun ständig den Timer auf seinen Zählerstand überwachen müssten, um einen Ablauf mit bestimmter Dauer zu erreichen. Für diese Aufgabe wurden Vergleicher eingebaut.

In der Regel haben alle Timer zwei Vergleicher, A und B. Mit dem Eintreten des Compare Match Ereignisses können automatische Vorgänge ausgelöst werden oder der Prozessor kann unterbrochen werden. Weiteres siehe spätere Lektionen.

4.1.4 Timer im CTC-Modus

CTC Die naheliegendste Anwendung der Vergleicher ist es, den Zähler bei Erreichen des Compare-Wertes auf Null zu setzen und von vorn beginnen zu lassen. Dies wird als CTC bezeichnet ("Clear timer on compare").

Man beachte, dass der Compare-Match nicht bei sofortiger Gleichheit rücksetzt, sondern erst mit Eintreten des nächsten Zählimpulses. Das garantiert eine exakt definierte Länge von Impulsen unabhängig von der physischen Vergleichsgeschwindigkeit. Im vorliegenden Fall wird das Vergleichsregister auf Neun eingestellt, womit 10 Zählimpulse Dauer zum CTC führen (Impulse 0 bis 9 = 10 Impulse).

CTC ist bei allen Timern mit dem Compare-Register A möglich. Compare-Register B kann für andere Zwecke verwendet werden. Manche AVRs verfügen auch noch über ein weiteres Register, mit dem ein weiterer CTC-Mode möglich ist und die Vergleicher A und B für andere Aufgaben frei sind.

4.1.5 Ausgänge mit dem Timer manipulieren

Die zweithäufigste Verwendung von Compare-Match ist das Setzen oder Löschen von Portpins. Damit macht sich der Match außerhalb bemerkbar und es können elektrische Impulse nahezu beliebiger Dauer an Ausgangspins erzeugt werden. Für den ATtiny13 ist PB0 für den Vergleicher A festgelegt (Ausgang OC0A), für B PB1 (OC0B).

Zur Verwendung genügt es, den entsprechenden Portpin als Ausgang zu definieren (seinen Ausgangstreiber einzuschalten, z.B. mit sbi DDRB,DDB0) und mit zwei Kontrollbits das Verhalten dieses Pins festzulegen. Vier Modi stehen zur Verfügung:
COM0A1
COM0B1
COM0AO
COM0B0
Funktion OC0A/OC0B
00Portpin wird nicht beeinflusst
01Portpin wechselt Polarität bei Compare Match (Torkeln, Toggle)
10Portpin bei Compare Match auf Null setzen
11Portpin bei Compare Match auf Eins setzen

Zur Beachtung: das gilt nur für den Fall, dass der Zähler im normalen Zählmodus betrieben wird. Für andere Modi passiert was anderes.

Damit stehen für die Blinkerei ganz neue Möglichkeiten zur Verfügung.

4.2 Hardware, Bauteile und Aufbau

Für die Blinker kommt die gleiche Hardware zum Einsatz, wie wir sie schon in Lektion 2 aufgebaut haben.
Home Top Einführung Hardware Standard CTC-Mode 128kHz-Modus

4.3 Timer mit Standardeinstellungen

4.3.1 Funktionsweise

Die einfachste Art, den Blinker zu bauen, ist den Timer bis 255 zählen zu lassen und bei einem Compare-Match den Ausgang torkeln zu lassen. Damit stellt sich eine Blinkfrequenz von

1.200.000 / 1.024 / 256 / 2 = 2,29 Hz

ein. Das ist schneller als es soll und wäre für eine Uhr ziemlich daneben.

4.3.2 Programm

Hier ist das Programm (Quellcode hier). Es schaltet zuerst den Portpin PB0 als Ausgang, setzt dann das Compare A Register, versetzt den Ausgang OC0A in den Toggle-Modus und startet den Timer mit dem durch 1024 geteilten Takt.

;
; *************************************
; * Timer zum Blinken                 *
; * (C)2016 by www.gsc-elektronic.net *
; *************************************
;
.NOLIST
.INCLUDE "tn13def.inc"
.LIST
;
; ---------- Register -----------------
.def rmp = R16 ; Vielzweckregister
;
; ---------- Timing -------------------
; Interner RC-Oszillator = 9.600.000 Hz
; Clock-Vorteiler CLKPR  =         8
; Interner Prozessortakt = 1.200.000 Hz
; TC0-Vorteiler          =     1.024
; TC0-Tick               =     1.171,875 Hz
; TC0-Durchlauf          =       256
; TC0-Durchlauffrequenz  =         4,578 Hz
; TC0-Toggle-Frequenz    =         2,289 Hz
;
; ---------- Start --------------------
	; PB0 als Ausgang
	sbi DDRB,DDB0 ; PB0 als Ausgang
	; setze Compare Match
	ldi rmp,0xFF ; Match bei 255
	out OCR0A,rmp ; in Compare Match A
	; toggle PB0 bei Compare Match
	ldi rmp,1<<COM0A0 ; Toggle Mode
	out TCCR0A,rmp ; in Kontrollregister A
	; Timer starten
	ldi rmp,(1<<CS02)|(1<<CS00) ; Prescaler 1024 
	out TCCR0B,rmp ; in Kontrollregister B
Schleife:
	rjmp Schleife

Die Instruktion "OUT" beschreibt alle acht Bits in einem Port gleichzeitig aus einem Register.

Nachdem die Hardware gestartet ist, wird der Prozessor nicht mehr benötigt und geht in eine unendliche Schleife (Schleife: rjmp Schleife).

TCCR0A Eine Besonderheit ist noch zu klären, die Formulierung "ldi rmp,1<<COM0A0". Damit wird das Portbit COM0A0 im Port TCCR0A auf Eins gesetzt. COM0A0 ist das Bit 6 in diesem Port. Eigentlich wäre zu schreiben: "ldi rmp,0b01000000" (0b startet eine Binärzahl). Spätestens eine Stunde nachdem wir das geschrieben haben, will uns nicht mehr einfallen, was "01000000" nun eigentlich heißt (dass es sich um das Bit COM0A0 handelt). Deshalb die Formulierung "ldi rmp,1<<COM0A0". Sie bedeutet Es ist wichtig zu verstehen, dass die Schieberei hierbei nur vom Assembler beim Übersetzen des Programmcodes vollzogen wird. << hat mit der Schiebeinstruktion des Prozessors nichts zu tun. Die gibt es nämlich auch, sie heißt "LSL" (Logical Shift Left) und braucht als Parameter ein Register, das nach Links geschoben werden soll.

TCCR0B In der Zeile "ldi rmp,(1<<CS02)|(1<<CS00)" werden gleichzeitig zwei Bits auf Eins gesetzt. Weil CS02 in der def.inc mit 2 definiert ist, CS00 aber mit Null, kommt bei den beiden Klammerausdrücken einerseits 0b00000100 (eine 1 zweimal links geschoben) und andererseits 0b00000001 (eine 1 keinmal links geschoben) heraus. Das Zeichen | sagt dem Assembler, die beiden Ergebnisse binär mit ODER zu verknüpfen, woraus dann 0b00000101 wird. Auch hier hat das nichts mit dem Prozessor zu tun, dessen ODER-Verknüpfung zweier Register heißt "OR". Das | macht allein der Assembler beim Übersetzen in Maschinencode.

Die Zeichen << und | sind mathematische Operatoren des Assemblers, wovon es noch viele weitere gibt. Wie z. B. +, -, * und /. Alles nur Mitteilungen an den Assembler, der Prozessor kriegt davon nichts mit.

4.3.3 Simulieren des Timers in diesem Modus

Die nachfolgende Simulation verwendet den Simulator avr_sim, um den Timer in diesem Modus nachzuahmen.

Timer zu Beginn Nach dem Initiieren ist der Timer TC0 in diesem Zustand:

Portausgang zu Beginn Nach der Initiierung ist das Richtungsbit DDB0 des Ports B Eins. Das bedeutet, dass der Ausgabepin PB0 dem Zustand des Portregisters PORTB0 folgt, auf niedriges Potential geht und die LED, die mit der Anode an der positiven Betriebsspannung liegt, eingeschaltet ist.

Der Timer zählt Nun zählt der Timer. Jeder Einzelschritt erhöht den Vorteilerwert. Erreicht der Vorteiler den Wert 1.024 wird das Portregister TCNT um Eins erhöht und der Vorteiler startet bei Null neu.

Timer erreicht Vergleichswert A Nach 256 * 1.024 = 262.144 Taktzyklen erreicht der Timer den Vergleichswert im Portregister "Compare A" und, wenn der nächste Taktimpuls eintritt, tritt ein Compare Match ein. Da der Timer damit auch seinen Höchstwert ("TOP") überschreitet, beginnt das Zählregister TCNT dann wieder bei Null (Zählerüberlauf).

Portbit PB0 torkelt Das Überschreiten des Compare-Match-A-Wertes lässt auch das Portbit PORTB0 torkeln, der Ausgangspin PB0 wird jetzt high und die LED wird ausgeschaltet. Diese Umschaltung erfolgt durch den Timer automatisch, dazu ist keinerlei weitere Prozessoraktivität nötig.

Stoppuhr Der Simulator hat zu diesem Zeitpunkt 131.079 Instruktionen ausgeführt, die meisten davon relative Sprünge RJMP, die zu ihrer Ausführung zwei Taktzyklen brauchen. 218,46 ms sind seit dem Start vergangen. Die Stoppuhr ("Stopwatch"), die nach der Initiierung zurückgesetzt worden ist, zeigt 218,452 ms an, was mit unseren vorberechneten 4,58 Timerzyklen pro Sekunde und einer Blinkfrequenz von 2,29 Hz übereinstimmt.

4.3.4 Vor- und Nachteile

Der Vorteil dieser Lösung im Vergleich zur Verzögerungsschleifen-Lösung in Lektion 3 ist, dass der Prozessor nicht mit Unsinn wie dem Abzählen von Schleifen beschäftigt wird. Der Zählvorgang läuft im Timer ab, der Schaltvorgang am Portpin wird vom Vergleicher erledigt. Der Prozessor könnte sich um andere Aufgaben kümmern, ohne dass die Zählerei und Schalterei irgendwie gestört würde.

Der Nachteil dieser Lösung ist, dass es mit der Sekundenblinkerei nicht hinhaut, das Blinken ist doppelt schneller. Ursache ist, dass das Teilen des Prozessortakts durch 1.024 und durch 256 immer krumme Werte liefert (es sei denn, der Prozessor liefe mit 2,4576 MHz Takt, wofür wir einen externen Taktgeber bräuchten) und weil der Takt 1,2 MHz zu schnell ist und die Vorteilerei zu groß für eine Sekunde ist. Daher müssen andere Lösungen her, bei denen der Prozessortakt entscheidend verlangsamt wird.

Home Top Einführung Hardware Standard CTC-Mode 128kHz-Modus

4.4 Timer im CTC-Modus

4.4.1 Funktionsweise

Prozessortakt verlangsamen

CLKPS-Bits Alle Tiny- und Mega-Typen des AVR neueren Datums haben eine Einrichtung, die das Teilen des Taktes interner und externer Oszillatoren ermöglichen, bevor diese auf den Prozessor und alle andere interne Hardware losgelassen werden. Als Teilerfaktoren stehen Zweierpotenzen von 1 bis 256 zur Verfügung. Bei 9,6 MHz internem RC-Oszillatortakt entspricht das 9,6 MHz bis 37,5 kHz Prozessortakt.

Ohne es zu wissen, haben wir diesen Vorteiler bereits praktisch verwendet. Er ist nämlich werksseitig auf das Teilen durch Acht eingestellt. Das können wir durch Löschen der CKDIV8-Fuse im Prozessor aufheben (siehe hier, wobei der Prozessor dann mit 9,6 MHz Takt läuft (Achtung! Bei niedrigen Betriebsspannungen schafft der langsamere Typ ATtiny13V diesen Takt nicht! Die Fuse kann dann nur mit erhöhter Betriebsspannung wieder gesetzt werden!).

CLKPR Um nicht nur 1 oder 8 als Teilerfaktoren verwenden zu können, muss auf den Port CLKPR zugegriffen werden. Damit das nicht aus Versehen passiert, gibt es eine bestimmte Prozedur, um das zu erledigen. Zuerst muss das Bit CLKPCE im Port CLKPR auf Eins gesetzt werden (alle anderen Bits MÜSSEN beim Schreiben Null sein). Sofort danach werden die CLKPS-Bits gesetzt (mit CLKPCE auf Null). Kurze Zeit später ist das Schreibzugriffsfenster wieder zu.

Das Setzen von 32 als Vorteiler erledigt man mit folgendem Programmcode:

	ldi R16,1<<CLKPCE ; Program Enable Bit auf Eins
	out CLKPR,R16 ; in Port CLKPR schreiben
	ldi R16,(1<<CLKPS2)|(1<<CLKPS0) ; Teiler = 32  
	out CLKPR,R16 ; in Port CLKPR schreiben

Nun läuft der Prozessor mit 9,6 MHz / 32 = 300 kHz Takt. Aber Obacht! Beim Programmieren mittels ISP muss jetzt auch der Takt niedriger (< 75 kHz) angesetzt werden, sonst meldet der Programmieradapter einen Fehler.

Strombedarf hohe Frequenzen Auf diese Weise wird der Prozessor zur lahmen Ente gemacht. Das macht man aber nur, wenn es denn nötig ist, wenn man z. B. Strom sparen will. Der Strombedarf ist nämlich etwa linear mit der Taktfrequenz, wie der nebenstehende Auszug aus dem Device Databook zeigt.

Strombedarf niedrige Frequenzen Mit der Herabsetzung der Taktfrequenz auf 300 kHz hat sich der Strombedarf des Prozessors von 1 bis 2 mA auf ganze 0,3 mA erniedrigt. Das tut einer Batterie oder einem Akku ganz gut und verfünffacht seine Haltbarkeit (als wenn es sonst nichts anderes anzutreiben gäbe).

Prozessor schlafen legen

Strombedarf Idle Eine wirksame Methode zum Stromsparen ist es, den Prozessor nicht in "Schleife: rjmp Schleife" zu schicken, wenn er nicht gebraucht wird, sondern ihn ganz schlafen zu legen. Dann stellt er das Lesen aus dem Flashspeicher, das Dekodieren und Ausführen von Instruktionen ganz ein. Das nennt sich Idle und bedeutet so viel wie Leerlauf.

Auch dieser Zustand muss erst eingeschaltet werden. Er lässt sich einschalten, indem das Sleep-Enable-Bit im Port MCUCR (Micro controler universal control register) gesetzt wird und die Sleep-Instruktion ausgeführt wird. Also etwa so:

	ldi R16,1<<SE ; Schlafen ermöglichen
	out MCUCR,R16 ; in Kontrollregister
	sleep ; schlafen legen

In unserem Fall weckt nichts mehr den Prozessor auf, nur das Programmiergerät mit einem Reset. Es gibt aber auch andere Weckmechanismen, die kommen aber erst später zum Einsatz.

Timer im CTC-Modus

Der Vergleicher A im Timer kann noch für eine weitere Betriebsart des Timers verwendet werden, nämlich den CTC-Modus. In unserem Fall kann man diese Betriebsart verwenden, um krumme, d. h. nicht-zweierpotenzige, aber ganzzahlige Teilerverhältnisse zu erreichen. Damit kommen wir näher an die Sekunde heran als im vorherigen Beispiel.

Timer-Modi Das hier sind alle Betriebsmodi des Timers. Der CTC-Modus ist einstellbar, indem das WGM1-Bit auf 1 gesetzt wird. Der höchste Wert des Timers (TOP) ist die im Port OCRA gespeicherte Zahl. Danach setzt der Timer wieder zurück.

WGM-Bits Die drei WGM-Bits WGM02, WGM01 und WGM00 des Timers 0 sind - unlogischerweise - in den zwei Ports TCCR0A und TCCR0B verteilt. Uns ficht das nicht an, da wir nur WGM01 auf Eins setzen müssen. Da dazu auch noch das Bit COM0A0 im TCCR0A zu setzen ist, kommt wieder das (1<<WGM01)|(1<<COM0A0) zum Einsatz.

4.4.2 Programm

Das riesige Programm ist hier gelistet (Quellcode hier). Zuerst wird die Taktfrequenz des Prozessors verstellt, dann das Portbit PB0 als Ausgang geschaltet, dann der Timer programmiert und zuletzt der Prozessor schlafen gelegt. Für den Fall, dass er aufwachen sollte, ist noch das erneute Schlafenlegen programmiert.

;
; *************************************
; * LED-Blinker mit Timer             *
; * (C)2016 by www.gsc-elektronic.net *
; *************************************
;
.NOLIST
.INCLUDE "tn13def.inc"
.NOLIST
;
; ------ Register ---------------------
.def rmp = R16 ; Vielzweckregister
;
; ------ Timing -----------------------
; Interner RC-Oszillator = 9.600.000 Hz
; Vorteiler CLKPR        =        32
; Taktfrequenz Prozessor =   300.000 Hz
; Vorteiler TC0          =     1.024
; Timer-Tick TC0         =       292,97 Hz
; Timer-CTC-Teiler       =       146
; Taktfrequenz CTC-OC0A  =         2,006 Hz
; Frequenz CTC-Toggle    =         1,003 Hz
;
; ------ Konstanten -------------------
.equ fRC = 9600000 ; Prozessortakt
.equ pClk = 32 ; Clock-Prescaler
.equ pTC0 = 1024 ; TC0-Prescaler
.equ pCtc = fRC / pClk / pTC0 / 2 ; Teiler
.equ cCtc = pCtc - 1 ; CTC-Wert
;
; ------ Programmstart ----------------
Start:
	; Die Taktfrequenz des Prozessors herabsetzen
	ldi rmp,1<<CLKPCE ; CLKPR-Schreiben ermoeglichen
	out CLKPR,rmp ; an CLKPR-Port
	ldi rmp,(1<<CLKPS2) | (1<<CLKPS0) ; Teiler = 32
	out CLKPR,rmp ; an CLKPR-Port6
	; PB0 als Ausgang
	sbi DDRB,DDB0 ; Datenrichtung Ausgang
	; Den Timer programmieren und starten
	ldi rmp,cCtc ; Den Vergleicherwert ...
	out OCR0A,rmp ; ... in das Compare-Register A schreiben
	ldi rmp,(1<<COM0A0) | (1<<WGM01) ; Toggle OC0A, CTC-Mode
	out TCCR0A,rmp ; in Kontrollregister A
	ldi rmp,(1<<CS02) | (1<<CS00) ; Vorteiler 1024
	out TCCR0B,rmp ; in Kontrollregister B
	;
	ldi rmp,1<<SE ; Schlafmodus Idle
	out MCUCR,rmp ; in Kontrollregister
Aufwachen:
	sleep ; Prozessor schlafen legen
	nop ; nach dem Aufwachen
	rjmp Aufwachen ; wieder schlafen legen
;
; Ende Quellcode
;	 

Nicht vergessen: der Prozessor arbeitet ab jetzt mit 300 kHz Takt, die ISP-Frequenz muss für das erneute Ansprechen mit dem Programmiergerät herabgesetzt werden.

4.4.3 Simulieren des Timerbetriebs im CTC-Modus

Wieder simulieren wir den Timer mit avr_sim.

Programm-Init Timer im CTC-Modus Das ist der Zustand nach der Initiierung. Die Taktfrequenz des Prozessors wurde durch das Schreiben in das CLKPR-Portregister auf 300 kHz herabgesetzt. Der Timer ist im CTC-Modus, mit dem Vergleichsregister Compare A als TOP-Wert. Der Pin PB0 torkelt bei Überschreiten des TOP-Werts.

Ende von Zählphase 1 Zählphase 1 Port Das ist der Zustand wenn das erste Compare-Match-Ereignis erreicht ist: 498 ms sind vorbei und das Portbit PB0 ist gesetzt, was die LED ausschaltet.

Zweites Compare Match Das zweite Compare-Match-Ereignis wird nach 996.69 ms erreicht. Das ist sehr nah an der Sekunde, aber nicht genau eine Sekunde.

4.4.4 Vor- und Nachteile

Der Strombedarf der Schaltung ist jetzt stark herabgesetzt, durch Takterniedrigung auf 300 kHz und Schlafmodus. Weniger geht nur noch, wenn wir die Betriebsspannung von 4,8 auf z. B. 3,3 V herabsetzen.

Nachteilig ist, dass wir noch immer nicht genau die eine Sekunde getroffen haben. Die Abweichung ist zwar viel geringer als die Abweichung des internen RC-Generators vom Soll-Wert (+/-10%), aber für eine Uhr selbst dann nicht zu gebrauchen, wenn wir einen externen Quarzoszillator anschließen würden.
Home Top Einführung Hardware Standard CTC-Mode 128kHz-Modus

4.5 Timer im 128kHz-Modus

Der ATtiny13 verfügt noch über einen weiteren internen RC-Oszillator, der per Fuse als Taktquelle ausgewählt werden kann. Er hat eine Frequenz von 128 kHz, die per CLKPR weiter geteilt werden kann, bis herunter auf 500 Hz. Tun Sie das nicht, es sei denn, sie haben ein Programmiergerät mit weniger als 125 Hz Taktfrequenz. Das AVRISPmkII kann 50,1 Hz, wäre also für diese Aufgabe noch geeignet.

4.5.1 Funktionsweise

Mit 128 kHz Taktfrequenz des Prozessors und des Timers muss für eine CTC-Toggle-Frequenz insgesamt durch 64.000 geteilt werden. 1.024 als Timer-Vorteiler führt bereits zu krummen 62,5 Hz. Mit 512 als Vorteiler muss der CTC auf 250 eingestellt werden, damit genau 2,00000 Hz Toggle-Frequenz herauskommen. Das ist mit dem 8-Bit-Timer im ATtiny13 realisierbar, der ja bis 255 zählen kann.

4.5.2 Programm

Das Programm ähnelt dem vorherigen, nur der Timer-Vorteiler und der CTC-Wert ist anders (Quellcode hier).

Bevor wir das programmieren, müssen wir die 32 im CLKPR aus dem vorherigen Experiment wieder loswerden. Dazu schreiben wir im vorherigen Program die Zeile "ldi rmp,(1<CLKPS2)|(1<CLKPS0)" in "ldi rmp,(1<CLKPS2)|(1<CLKPS0)" um, assemblieren und programmieren das Ergebnis in den Chip. Nun ist der CLKPR wieder "normal" und es kann das folgende programmiert werden. Wir können dies aber auch lassen und stattdessen die CKDIV8-Fuse vorübergehend setzen (siehe unten).

;
; ****************************************
; * Blink mit Timer, RC-Osz. mit 128 kHz *
; * (C)2016 by www.gsc-elektronic.net    *
; ****************************************
;
.NOLIST
.INCLUDE "tn13def.inc"
.LIST
;
; ------- Register -----------------------
.def rmp = R16 ; Vielzweckregister
;
; ------- Timing -------------------------
; Interner RC-Oszillator = 128.000 Hz
; Clock-Vorteiler CLKPR  =       1
; Interne Taktfrequenz   = 128.000 Hz
; TC0-Vorteiler          =     256
; TC0-Timertick          =     500 Hz
; TC0-CTC-Teiler         =     250
; TC0-Togglefrequenz     =       1 Hz
;
; --------- Konstanten -------------------
.equ cCtc = 250-1
;
; --------- Programm ---------------------
	; PB0 als Ausgang
	sbi DDRB,DDB0 ; Portbit als Ausgang
	; Timer Compare-Match A auf 250
	ldi rmp,cCtc ; Match-A-Wert
	out OCR0A,rmp ; in Match-Register A
	; Timer als CTC und Toggle Ausgang A
	ldi rmp,(1<<COM0A0)|(1<<WGM01) ; Toggle und CTC
	out TCCR0A,rmp ; in Kontrollregister A
	ldi rmp,1<<CS02 ; Vorteiler auf 256
	out TCCR0B,rmp ; in Kontrollregister B
	; Schlafen ermoeglichen
	ldi rmp,1<<SE
	out MCUCR,rmp
	; Schlafschleife
Schleife:
	sleep ; schlafen legen
	nop ; nach Aufwachen
	rjmp Schleife
;
; Ende Quellcode
;

Fuse-Einstellung Programmiert man das in den Tiny, blinkt es hektisch, da der Takt noch bei 1,2 MHz liegt. Jetzt müssen wir den Takt auf den internen 128 kHz-Oszillator einzustellen. Dazu wird in der Fuses-Abteilung der Programmiertools der 128 kHz-Oszillator ausgewählt und der Haken bei der CKDIV8-Fuse entfernt. Das ganze geht mit dem Button "Program" an das Programmiergerät und hat hoffentlich das taktvolle Ein-Sekunden-Blinken der LED zur Folge.

4.5.3 Simulation des Timerbetriebs bei 128 kHz Takt

Simulation mit avr_sim ergibt Folgendes.

Simulation nach Init TC0 nach Init Nach dem Init mit einer Taktfrequenz von 128 kHz sind 62,5 µs vergangen. Der Timer ist im CTC-Modus mit dem Compare-Register A als TOP-Wert.

Nachdem der erste Compare Match auftrat sieht die Simulation so aus:

Simulation erstes Compare Match Port beim ersten Compare Match TC0 nach erstem Compare Match

Die simulierten Zeiten sind ziemlich genau.

Simulation zweites Compare Match Port beim zweiten Compare Match Alles ist korrekt beim zweiten Compare Match.

4.5.4 Vor- und Nachteile

Jetzt stimmt das Teilerverhältnis zwar theoretisch ganz genau, über die Genauigkeit des 128 kHz-Oszillators schweigt sich ATMEL in seinen Datenblättern aber völlig aus. Um einen externen Quarzoszillator kommen wir also bei einer Uhr nicht herum. Immerhin hat die ganze komplizierte Timing-Mimik nun einen Stromverbrauch, der bei einem Fünfzigstel der LED liegt.
Home Top Einführung Hardware Standard CTC-Mode 128kHz-Modus

©2016-2018 by http://www.gsc-elektronic.net