www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATtiny2313 Timer1 Problem


Autor: Benjamin K. (exs)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas K. (a-k)
Datum:

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

Autor: TIMER_MAN (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: TIMER_MAN (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 .

Autor: Benjamin K. (exs)
Datum:

Bewertung
0 lesenswert
nicht 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
Start:
  
  ; Interrupt aktivieren
  LDI r16,(1<<TOIE1)
  OUT TIMSK,r16

  ; Timer1 Zeit laden
  LDI r16,$79
  OUT TCNT1L,r16

  LDI r16,$FE
  OUT TCNT1H,r16

  ; Timer1 starten
  LDI r16,$04
  OUT TCCR1B,r16

Final:

  RJMP Final

Timer1Overflow:
  
  ... ; Register retten

  ; Timer1 stoppen
  LDI r16,$00
  OUT TCRR1B,r16

  ; Timer1 Zeit laden
  LDI r16,$04
  OUT TCNT1L,r16

  LDI r16,$A7
  OUT TCNT1H,r16

  ; Timer1 starten
  LDI r16,$04
  OUT TCCR1B,r16

  ... ; Register wiederherstellen und Interrupt beenden

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Troll Blaubär (blaubeer)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Benjamin K. (exs)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Benjamin K. (exs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
;-) Das sehe ich weniger als Problem an

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.