Forum: Compiler & IDEs ATMega16 - Timer - Verständnisproblem


von Falk (Gast)


Lesenswert?

Hallo allerseits (jetzt hoffentlich im richtigen Forum?)!
Ich experimentiere hier gerade mit dem 16-Bit Timer und einem
LED-Lauflicht herum.
Leider scheint mein Verständnis von diesem Timer vollkommen falsch zu
sein.

Zu meiner Schaltung: Am ATMega16 hängt ein 11,0592MHZ Quarz (wie in den
meisten Tutorials) und ein LED Lauflicht mit 8 LEDs.

In meinem Programm habe ich den Timer nun mit einem Prescaler von 256
versehen (d.h. Bit CS12 gesetzt).
Das OutputCompare Register steht zur Zeit auf "OCR1A = 0x0002".

Das ganze löst dann ein Interrupt aus, welches wiederum einen Zähler
erhöht. Wenn der bei 1000 angekommen ist, schalte ich das Lauflicht um 1
weiter.
Was ich also gerne hätte ist, dass das OutputCompareMatch genau jede
Millisekunde ausgelöst wird, so dass das Licht jede Sekunde um 1
weitergeht.


Allerdings läuft das ganze UNENDLICH langsam. Anstatt jede Sekunde
dauert es fast 20 Sekunden, bis die LED weiterspringt. Ich habe auch
schon mit allen möglichen Werten für das CompareRegister und den
Prescaler rumprobiert, aber es will einfach nicht.

Meine Rechnung:
Wenn der Quarz 11,0592MHZ hat, und der Prescaler bei 256 liegt, läuft
das ganze noch mit 43.200HZ.
Da mein Compare Register auf 2 steht, müsste eigentlich 22.000 pro
Sekunde "interrupted" werden, richtig (das ergäbe zwar keinen
MilliSekundentakt, aber trotzdem was ganz schnelles)?
Aber warum ist das ganze dann soooooo langsam?

PS:
Wie kann man eigentlich feststellen, ob der AVR überhaupt den Quarz 
nutzt?
ABer selbst wenn nicht: müsste es dann nicht trotzdem schnell genug 
laufen?

von OliverSo (Gast)


Lesenswert?

>Wie kann man eigentlich feststellen, ob der AVR überhaupt den Quarz
>nutzt?

Indem man über einen Timer eine LED blinken lässt :-)
Das aber am besten mit einem erprobten Beispielcode.

Oliver

von Johannes M. (johnny-m)


Lesenswert?

Falk wrote:
> Hallo allerseits (jetzt hoffentlich im richtigen Forum?)!
Nicht wirklich. µC & Elektronik wäre angebrachter gewesen...

> Ich experimentiere hier gerade mit dem 16-Bit Timer und einem
> LED-Lauflicht herum.
> Leider scheint mein Verständnis von diesem Timer vollkommen falsch zu
> sein.
Das lässt sich möglicherweise ändern...

> Zu meiner Schaltung: Am ATMega16 hängt ein 11,0592MHZ Quarz (wie in den
> meisten Tutorials) und ein LED Lauflicht mit 8 LEDs.
>
> In meinem Programm habe ich den Timer nun mit einem Prescaler von 256
> versehen (d.h. Bit CS12 gesetzt).
> Das OutputCompare Register steht zur Zeit auf "OCR1A = 0x0002".
Schön. Und wo ist dieses Programm?

> Das ganze löst dann ein Interrupt aus, welches wiederum einen Zähler
> erhöht. Wenn der bei 1000 angekommen ist, schalte ich das Lauflicht um 1
> weiter.
> Was ich also gerne hätte ist, dass das OutputCompareMatch genau jede
> Millisekunde ausgelöst wird, so dass das Licht jede Sekunde um 1
> weitergeht.
Wenn Du eh nur nen Sekundentakt brauchst, den kannste mit dem 
16-Bit-Timer auch direkt erzeugen.

> Allerdings läuft das ganze UNENDLICH langsam. Anstatt jede Sekunde
> dauert es fast 20 Sekunden, bis die LED weiterspringt. Ich habe auch
> schon mit allen möglichen Werten für das CompareRegister und den
> Prescaler rumprobiert, aber es will einfach nicht.
>
> Meine Rechnung:
> Wenn der Quarz 11,0592MHZ hat, und der Prescaler bei 256 liegt, läuft
> das ganze noch mit 43.200HZ.
> Da mein Compare Register auf 2 steht, müsste eigentlich 22.000 pro
> Sekunde "interrupted" werden, richtig (das ergäbe zwar keinen
> MilliSekundentakt, aber trotzdem was ganz schnelles)?
> Aber warum ist das ganze dann soooooo langsam?
Nicht ganz.
(f_COMP ist die Frequenz, mit der das Compare-Ereignis auftritt)
Du hast also bei OCRnX = 2 einen Teiler von 3. Um die Frequenz zu 
halbieren, müsstest Du eine 1 in OCR1A schreiben.

EDIT:
Zum Verständnis: Wenn ein Compare-Ereignis auftritt (also 
Übereinstimmung der Werte in TCNTn und OCRnX), dann wird das 
Compare-Flag (das u.a. zum Auslösen des dazugehörigen Interrupt genutzt 
werden kann) erst mit dem folgenden Timer-Takt gesetzt. Das führt zu 
dem "OCRnX + 1" in der Berechnung. Wäre das nicht der Fall, dann könnte 
man sich vorstellen, dass eine Null im Compare-Register den µC vor 
gewisse Probleme stellen würde...

> PS:
> Wie kann man eigentlich feststellen, ob der AVR überhaupt den Quarz
> nutzt?
> ABer selbst wenn nicht: müsste es dann nicht trotzdem schnell genug
> laufen?
Indem man entweder kontrolliert, ob man die Fusebits korrekt gesetzt hat 
oder indem man mit einem Oszilloskop überprüft, ob der Oszillator mit 
dem externen Quarz oder wasauchimmer läuft oder indem man einen 
sichtbaren Vorgang mit bekannter Periode programmiert (LED blinken).

Ich tippe mal, dass der µC mit internem RC-Oszillator, 1 MHz läuft 
(Werkseinstellung!). Das macht zusammen mit Deinem Rechenfehler in OCR1A 
ungefähr einen Faktor von 17, was mit den ca. 20 s anstatt einer Sekunde 
übereinstimmen würde.

Ansonsten ist es meist sehr hilfreich, den Programmcode anzuhängen. 
Sonst kann man an vielen Stellen nur raten, was Du da wirklich gemacht 
hast.

von Jörg X. (Gast)


Lesenswert?

Wenn du schon im GCC-Forum postest, wie wäre es mit etwas Code? ;)
und ich hab (deshalb) ein paar fragen:
 - in welchem Modus läuft der Timer -- normal-mode?, dann muss der Timer 
erstmal durchlaufen, bevor es wieder einen Intrrupt gibt, das ist ein 
16-Bit timer, es kann also etwas dauern -- du willst wahrscheinlich CTC, 
d.h. der Timer soll jedes mal, wenn ein OC-interrupt eintritt, wieder 
von vorne anfangen.
 - Um den Quarz zu nutzen musst du auf "Crystal Oscillator" fuse'n, 
NICHT "external clock" oder "external RC-Oscillator", ich weiß aber 
nicht womit du programmierst (für den AVRDude 'geistern ' hier im Forum 
zwei Java-GUIs herum)

Probier bei dem Timer mal: Prescaler 1, Mode 4 (CTC mit OCR1A als 
TOP-wert), setz OCR1A auf 11060 und nimm den Outputcompare interrupt 1A
(wieso 11060: 0.001s *11059200Hz [Hz == 1/s] )

hth. Jörg

von Johannes M. (johnny-m)


Lesenswert?

...Ach ja, was Jörg schon andeutete, ist natürlich auch korrekt: Der 
Timer muss, damit das funktioniert, natürlich im CTC-Modus laufen...

von Jörg X. (Gast)


Lesenswert?

Ooh, da war ich ja recht langsam beim Tippen...
Hoffentlich funktionieren heute die Glaskugeln ;)

scnr --Jörg

von Falk (Gast)


Angehängte Dateien:

Lesenswert?

OK, hier der Code.
Und ein Bild der Fuses aus PonyProg (an die ich micht mehr rantraue, 
seitdem ich einen AVR gehimmelt hab) ;-)

http://img260.imageshack.us/my.php?image=fusesth3.jpg

von Falk (Gast)


Angehängte Dateien:

Lesenswert?

Uah, fehler beim Erstellen der .c Datei. Die am besten mit Wordpad 
öffnen, oder diese hier benutzen. Sorry!

von Karl H. (kbuchegg)


Lesenswert?

Hast du einen Quarz oder einen Quarzoszillator?

So wie die Fuses da stehen, wird ein Quarz nicht benutzt ->
Der Mega32 läuft mit 1 Mhz

Bei einem Quarz sind bei CKSEL0 bis CKSEL3 in PonyProg
keine Häkchen gesetzt.

von Falk (Gast)


Lesenswert?

"Hast du einen Quarz oder einen Quarzoszillator?"
Hä? Ich dachte Quarz wäre Quarz... was ich habe ist ein recht kleines 
Gehäuse mit 2 Füßchen. Oben steht 11,0592MHZ drauf.

von Karl H. (kbuchegg)


Lesenswert?

Falk wrote:
> "Hast du einen Quarz oder einen Quarzoszillator?"
> Hä? Ich dachte Quarz wäre Quarz... was ich habe ist ein recht kleines
> Gehäuse mit 2 Füßchen. Oben steht 11,0592MHZ drauf.

OK. Das ist ein Quarz.

Na dann: Deine Fuses stehen nicht richtig für einen Quarz.
Dein Mega32 läuft mit 1 Mhz.

von Falk (Gast)


Lesenswert?

Aha! :-)
Muss ich dann also alle Häkchen bei CKSEL in PonyProg aus machen?

von Karl H. (kbuchegg)


Lesenswert?

In PonyProg sind bei einem Quarz bei
den Einstellungen CKSEL0, CKSEL1, CKSEL2, CKSEL3
keine Häkchen gesetzt.

Dies entspricht in ATMEL Notation einer Einstellung 1111
und die ist laut Datenblatt für Quarze (External Crystal)
vorgesehen.

von Karl H. (kbuchegg)


Lesenswert?

Bei CKOPT könntest du auch noch ein Häkchen machen.

CKOPT - Häkchen  -> CKOPT = 0
Das wiederrum bedeutet, dass der interne Verstärker
auf volle Leistung gestellt wird, sozusagen.

von Karl H. (kbuchegg)


Lesenswert?

Und ganz wichtig!

Bevor du die Fuses umstellst: Im Dialog die Fuses
vorher einlesen lassen!

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.