Forum: Mikrocontroller und Digitale Elektronik ATtiny2313 Timer1 Problem


von Benjamin K. (exs)


Lesenswert?

Moin,

ich hab da mal ne Frage zum Timer1 des ATtiny2313.
Also ich habe ein Programm geschrieben, welches den Timer1 so benutzt, 
dass er rein rechnerisch nach 100ms einen Overflow auslösen müsste.

Es wird der interne Quarz als Taktquelle benutzt (1Mhz).

Also
1Mhz entspricht 1 µs

Daraus folgt 100ms entsprechen 100 000 Zähltakten mit Prescaler 1. Mit 
Prescaler 256 sind es rund 391 Zähltakte. Da Timer1 aufwärts zählt macht 
das also einen Startwert von 65145.

Merkwürdigerweise machen das meine Tinys (hab 12 Stück) aber nicht. Bei 
mir dauert es statt 100ms knappe 17s (man beachte den Faktor von 170!) 
im ersten Durchlauf. Danach funktioniert das Programm wie gewünscht.

Woran kann das liegen?

Die Programmstruktur ist:
Interrupt für Timer1 aktivieren
Interrupts generell zulassen
Startzeit für Timer 1 laden
Timer1 starten
Endlosschleife

Interrupt Timer 1:
Register sichern
Timer 1 stoppen
Irgendwas machen
Startzeit für Timer 1 laden (kann von 100ms Laufzeit abweichen)
Timer1 starten
Register wieder herstellen
Interrupt beenden

PS.: Die Zeit von 17s hab ich mit einem Oszi ermittelt.

von Andreas K. (a-k)


Lesenswert?

Der Timer läuft offensichtlich beim ersten Mal die ganzen 64K durch. 
Programm wäre hilfreich.

von TIMER_MAN (Gast)


Lesenswert?

Timer 0-1-2 Berechnungstool

Das Tool sollte dir helfen erzeug gleich den passenden code in bascom.
Ich hoffe du kannst was damit anfangen.

http://bascom-forum.de/index.php/topic,114.msg343.html#msg343

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Hast du die CLKDIV Fuse deaktiviert? Sosnt läuft der Tiny nämlich nicht 
mit 1 Mhz sondern mit 1/8 Mhz...
Oder lädst du beim erstenmal nicht die Zeit richtig?

von Johannes M. (johnny-m)


Lesenswert?

So was macht man beim AVR nicht mit Preload. Dafür gibts bei den meisten 
Timern (und auch beim Timer1 vom Tiny2313) die CTC-Betriebsart, die über 
die Compare-Einheit arbeitet.

von TIMER_MAN (Gast)


Lesenswert?

CTC geht nur mit Timer1 und 2 timer0 hat
kein compare mode.
und wie man den Timer verwendet ist geschmackssache.
CTC nehme ich nur wenn ich eine IF-Diode mit 36 KHz
Timen möchte .

von Benjamin K. (exs)


Lesenswert?

@Andreas Kaiser:
Offensichtlich hast du recht, aber wieso?

@TIMER_MAN:
Bascom benutze ich nicht, ausserdem scheinen die Berechnungen ja zu 
stimmen (zumindest im zweiten Durchlauf, siehe Programmcode).

@Läubi:
Nein die Fuse ist nicht gesetzt, also CLKDIV = 1, damit läuft der Tiny 
mit 1MHz, sonst mit 8MHz, siehe Manual auf Seite 25: Default Clock 
Source; Ebenfalls mit Oszi überprüft.

@Johannes M.:
Könntest du das näher erläutern? Was wäre denn der Unterschied ob ich 
von 0 bis x zähle oder von x bis 65535 und den Overflow nutze? Ausserdem 
ist das nicht ganz ohne, wie die Erläuterung auf Seite 99 des Handbuchs 
zeigt (das Beispiel, wenn man den oberen Wert nahe dem unteren wählt, 
was ja dann hier der Fall wäre).

Programmcode, nur relevante Teile:
65145 in Hex: $FE79
1
Start:
2
  
3
  ; Interrupt aktivieren
4
  LDI r16,(1<<TOIE1)
5
  OUT TIMSK,r16
6
7
  ; Timer1 Zeit laden
8
  LDI r16,$79
9
  OUT TCNT1L,r16
10
11
  LDI r16,$FE
12
  OUT TCNT1H,r16
13
14
  ; Timer1 starten
15
  LDI r16,$04
16
  OUT TCCR1B,r16
17
18
Final:
19
20
  RJMP Final
21
22
Timer1Overflow:
23
  
24
  ... ; Register retten
25
26
  ; Timer1 stoppen
27
  LDI r16,$00
28
  OUT TCRR1B,r16
29
30
  ; Timer1 Zeit laden
31
  LDI r16,$04
32
  OUT TCNT1L,r16
33
34
  LDI r16,$A7
35
  OUT TCNT1H,r16
36
37
  ; Timer1 starten
38
  LDI r16,$04
39
  OUT TCCR1B,r16
40
41
  ... ; Register wiederherstellen und Interrupt beenden

von Andreas K. (a-k)


Lesenswert?

Hier passt der CTC Mode besser, weil nur der ein präzises Intervall 
garantiert (z.B. WGM1x=1100 in TCCR1A/B).

Dein Problem allerdings hängt mit der Reihenfolge zusammen, in der du 
den Timer schreibst. Du schreibst nämlich nicht wirklich ins "high" 
Register, sondern tatsächlich in ein Temp-Register, das zusammen mit dem 
darauf folgenden Schreibzugriff aufs "low" Register dann im Timer 
landet. Und das passiert erst beim ersten Interrupt

Steht übrigens in der Doku.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Erm... bei mir steht:

>> The device is shipped with CKSEL = “0010”, SUT = “10”,
>> and CKDIV8 programmed.

und in der Tabelle für ClockSources steht:
>> Device Clocking Option CKSEL3..0
>> External Clock 0000 - 0001
>> Calibrated Internal RC Oscillator 4MHz 0010 - 0011
>> Calibrated internal RC Oscillator 8MHz 0100 - 0101
>> Watchdog Oscillator 128kHz 0110 - 0111
>> External Crystal/Ceramic Resonator 1000 - 1111

Ergo: Auslieferungszustand = 4Mhz/8 = 500kHz
Oder überseh ich jezt was?

Ansosnten hat >>Andreas Kaiser<< recht: Reihenfolge beim 
Lesen/Beschreiben von 16bit Registern beachten!

von Johannes M. (johnny-m)


Lesenswert?

Benjamin K. wrote:
> @Johannes M.:
> Könntest du das näher erläutern? Was wäre denn der Unterschied ob ich
> von 0 bis x zähle oder von x bis 65535 und den Overflow nutze? Ausserdem
> ist das nicht ganz ohne, wie die Erläuterung auf Seite 99 des Handbuchs
> zeigt (das Beispiel, wenn man den oberen Wert nahe dem unteren wählt,
> was ja dann hier der Fall wäre).
Bei einem Preload musst Du im Interrupt Handler jeweils den Startwert 
wieder ins Zählregister schreiben (und dabei die Hinweise in Bezug auf 
16-Bit-Register beachten). Das kann insbesondere bei kurzen Zeiten zu 
Ungenauigkeiten führen, weil der Timer verzögert "nachgeladen" wird. 
Schließlich braucht es einige Taktzyklen vom Auftreten des Interrupts 
(Flag wird gesetzt) bis zum Beginn des eigentlichen Interrupt Handlers. 
In Assembler kann man das zwar sehr präzise kontrollieren und 
kompensieren (indem man den Nachladewert entsprechend anpasst), aber es 
ist unnötiger Programmieraufwand.

Im CTC-Modus schreibst Du einmal den Wert ins Compare-Register und 
brauchst Dich danach nicht mehr drum zu kümmern, solange der Wert 
konstant bleibt. Und wenn man erforderliche Änderungen am Compare-Wert 
synchronisiert (also im entsprechenden Interrupt-Handler) durchführt, 
kommt es i.d.R. auch nicht zu den von Dir angedachten Problemen.

von Gast (Gast)


Lesenswert?

Eines ist mir in deinem Programm noch aufgefallen:
muss bei den 16bit Timerregistern nicht der Timer H-Wert zuerst gladen 
werden?

Warum und wieso steht in der Beschreibung der Timer.

von Troll B. (blaubeer)


Lesenswert?

Um beide Compares und den Capture nutzen zu können, verzichte ich meist 
auf den CTC-Mode und lasse Timer1 frei durchlaufen. Im Compare lese ich 
OCR aus, addiere das Intervall dazu und schreibe ins OCR zurück. Das ist 
zwar etwas mehr Programmieraufwand als CTC, ist aber auch jitterfrei, da 
die Zählerei des Timers dadurch nicht berührt wird.

Preload des Timerstandes macht man eigentlich nur noch bei Timern, die 
kein Compare haben und deren Vorteiler so hoch (langsam) ist, dass 
sichergestellt ist, dass der Timer beim Laden noch 0 war.

MfG, BlauBär

von Benjamin K. (exs)


Lesenswert?

@Läubi:
Also wenn ich das nicht falsch verstehe, dann steht da:
... and an initial system clock prescaling of 8, resulting in 1.0 MHz 
system clock. ...

Also ein Teiler von 8 sorgt für 1MHz Takt, was ich ja auch über den 
CKOUT-Pin mit dem Oszi nachmessen konnte.

@Andreas:
Das mit der Reihenfolge hats gebracht, danke. Ich habe mein Programm nun 
so geändert, dass die Timerstartwerte erst in zwei Register geladen 
werden, also das untere Byte in ein Regster das obere in das andere 
Register (möchte nachher Werte aus dem Flash laden). Anschließend werden 
die Werte dann in der richtigen Reihenfolge, wie in der Application Note 
doc1493.pdf angegeben, in das TCNT1-Register geladen. Der Wert wird in 
meinem Programm nicht konstant bleiben. Es ist für meine Anwendung auch 
kein Problem wenn der Timer mal etwas länger oder kürzer läuft, hatte 
mich nur über die sehr lange Laufzeit im ersten Zyklus gewundert.

mfg Benny -> solved

von Andreas K. (a-k)


Lesenswert?

Kleiner Tip noch zum Assembler:
  ldi r16, low(65145)
  ldi r17, high(65145)
liest und schreibt sich leichter als der Umweg über handgerechnete 
Hex-Werte.

von Benjamin K. (exs)


Lesenswert?

;-) Das sehe ich weniger als Problem an

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.