Hallo,
ich möchte den Timer 2 des Atmega88 via TOSC1 und TOSC2 mittels eines
Uhrenquarzes betreiben, um einen sekundengnauen Overflow zu erhalten.
Diesen benötige ich um einen einstellbaren Countdown von max. 00:15:00
runter zählen zu lassen.
Nur habe ich ein paar Probleme bei der Konfiguration bzw. bei den
Ausführungen im Atmel Datenblatt.
Mein Ansatz war die Konfiguration zu Beginn der Main, wie folgt vor
zunehmen:
TIMSK2 &=(~(1<<TOIE2)|(1<<OCIE2A)|(1<<OCIE2B));
ASSR |= (1<<EXCLK);
ASSR |= (1<<AS2);
TCCR2B |= (1<<CS22)|(1<<CS20);
TCNT2 = 0x00;
while(ASSR & (1<<TCN2UB));
TIMSK2 &=(~(1<<TOIE2)|(1<<OCIE2A)|(1<<OCIE2B));
TIMSK2 |= (1<<TOIE2);
sei();
entsprechend der Angaben im Datenblatt:
"Warning: When switching between asynchronous and synchronous clocking
of
Timer/Counter2, the Timer Registers TCNT2, OCR2x, and TCCR2x might be
corrupted. A safe
procedure for switching clock source is:
a. Disable the Timer/Counter2 interrupts by clearing OCIE2x and TOIE2.
b. Select clock source by setting AS2 as appropriate.
c. Write new values to TCNT2, OCR2x, and TCCR2x.
d. To switch to asynchronous operation: Wait for TCN2xUB, OCR2xUB, and
TCR2xUB.
e. Clear the Timer/Counter2 Interrupt Flags.
f. Enable interrupts, if needed."
Doch seit ich dies eingefügt habe, funktionier garnichts mehr in meinem
vorher funktionierenden Programm. Auch bei der Compilierung mittels AVR
Stuido 4 treten keine Fehler auf.
Ich hoffe auf eure Untersützung beim Konfigurieren des Timers.
Eine folgende Frage ist, ob es möglich ist nur das TOV2 Bit des TIFR2
abzufragen um damit quasi außerhalb einer ISR den Zähltakt der Uhr zu
erzeugen. Sprich ob dies dann ohne eigentliche ISR mögliche wäre, auch
das wurde mir aus dem Datenblatt leider nicht deutlich.
Für zielführende Tips schon mal vielen Dank im Voraus.
Gruß Michel
> ich möchte den Timer 2 des Atmega88 via TOSC1 und TOSC2 mittels eines> Uhrenquarzes betreiben, um einen sekundengnauen Overflow zu erhalten.> ASSR |= (1<<EXCLK);
• Bit 6 – EXCLK: Enable External Clock Input
When EXCLK is written to one, and asynchronous clock is selected, the
external clock input buffer is enabled and an external clock can be
input on Timer Oscillator 1 (TOSC1) pin instead of a 32 kHz crystal (=
Uhrenquarz!). Writing to EXCLK should be done before asynchronous
operation is selected. Note that the crystal Oscillator (= Uhrenquarz!)
will only run when this bit is zero.
> Eine folgende Frage ist, ob es möglich ist nur das TOV2 Bit des TIFR2> abzufragen um damit quasi außerhalb einer ISR den Zähltakt der Uhr zu> erzeugen. Sprich ob dies dann ohne eigentliche ISR mögliche wäre, auch> das wurde mir aus dem Datenblatt leider nicht deutlich.
Halte ich für möglich, kann mir aber den Sinn nicht vorstellen.
Was an dem von Krapao geposteten Datenblatt-Zitat war missverständlich?
1
TIMSK2&=(~(1<<TOIE2)|(1<<OCIE2A)|(1<<OCIE2B));
Wegen falscher Klammerung nahezu unwirksam. Glücklicherweise ja aber eh
unnötig, oder hast du irgendwann vorher eines der Bits gesetzt?
Wo sind die Punkte d und e aus deinem eigenen Datenblatt-Zitat?
Vielen Dank für eure Antworten.
Klar das invertieren der Interruptenablebits, muss natürlich anders
aussehen.
Ist mir gestern allein nicht mehr aufgefallen, aber ich bin auch in
keinsterweise sicher in C Programmierung und erst seit ein paar Wochen
in Sachen AVRs und Programmierung dabei...sorry.
Der Datenblatttext(siehe post Krapao) zu Bit6(EXCLK) des ASSR bleibt für
mich dennoch missvertändlich, da zum Einen davon gesprochen wird, dass
das Bit logisch 1 sein soll im asynchronen Modus um den Uhrquarz
betreiben zu können, zum Anderen der letzte Satz "Note that the crystal
Oscillator will only run when this bit is zero." oder ist hiermit der
Quarz an XTAL gemeint???
ASSR &= ~(1<<EXCLK) od. ASSR |= (1<<EXCLK);
TIMSK2 &= ~((1<<TOIE2)|(1<<OCIE2A)|(1<<OCIE2B));
ASSR |= (1<<AS2);
TCCR2B |= (1<<CS22)|(1<<CS20);
TCNT2 = 0x00;
while(ASSR & (1<<TCN2UB)); //Punkt d
TIMSK2 &= ~((1<<TOIE2)|(1<<OCIE2A)|(1<<OCIE2B)); //Punkt e
TIMSK2 |= (1<<TOIE2);
Ich habe mir über den Vorteiler die Zeit etwas besser einteilbar
gemacht.
Vielleicht hilft dir das ja schon weiter, habe mich auch mal mit dem
Thema beschäftigt, aber weis leider nicht mehr genau wo das Problem lag.
Gruß,
Martin
> while(ASSR & (1<<TCN2UB)); //Punkt d
Ich würde mich nicht darauf verlassen, dass es reicht, sich eines der
Bits rauszupicken. Ich würde tatsächlich auf alle Bits warten, deren
zugehörige Register du beschrieben hast (zumal man das ja auch in nur
einer Schleife machen kann).
> TIMSK2 &= ~((1<<TOIE2)|(1<<OCIE2A)|(1<<OCIE2B)); //Punkt e
Nein, das ist nicht Punkt e. Der sagt "Flags löschen", nicht
"Enable-Bits löschen".
Und so nebenbei: der Code von Martin macht das auch nicht korrekt.
Hallo Stefan,
auf dein Statement hin muss ich dann doch nochmal fragen.
Hab es jetzt wie folgt umgeschrieben:
ASSR &= ~(1<<EXCLK);
TIMSK2 &= ~(1<<TOIE2);
ASSR |= (1<<AS2);
for(w=0,w<=ww,w++)
{
_delay_ms(10);
}
TCCR2B |= (1<<CS22)|(1<<CS20); // Prescaler 128
TCNT2 = 0x00;
while(ASSR & (1<<TCN2UB));
TIFR2 &= ~(1<<TOV2);
TIMSK2 |= (1<<TOIE2);
1. zu deiner Aussage bezüglich der Wartefunktion:
Ich laden doch nur TCNT2 mit einem Anfangswert und lasse die andere
Register des Zählers doch unangetatet bzw. möchte ich den Timer 2
auch nur zu diesem Zweck und keinem Compare und dergleichem mehr
nutzen.
Stellst du dir das dann wie folgt vor?
while(ASSR &((1<<TCN2UB)|(1<<OCR2AUB)|(OCR2BUB)|
(1<<TCR2AUB)|(1<<TCR2BUB));
2. Okay der Timer hat mehrere Interrupts, sicher muss man dann alle
entsprechenden Flags löschen.
TIFR2&=~((1<<OCF2B)|(1<<OCF2A)|(1<<TOV2))
> 2. Okay der Timer hat mehrere Interrupts, sicher muss man dann alle> entsprechenden Flags löschen.> TIFR2&=~((1<<OCF2B)|(1<<OCF2A)|(1<<TOV2))
Steht im Datenblatt
Aber normalerweise löschen sich die Flags von alleine dur ch einen
Registerzugriff oder man schreibt eine 1 hinein.
ACHTUNG man schreibt eine 1 hinein ZUM LÖSCHEN ! Keine 0 !
Michel Schl. schrieb:> 1. zu deiner Aussage bezüglich der Wartefunktion:> Ich laden doch nur TCNT2 mit einem Anfangswert und lasse die andere> Register des Zählers doch unangetatet
Und was ist mit TCCR2B?
Michel Schl. schrieb:> Stellst du dir das dann wie folgt vor?> while(ASSR &((1<<TCN2UB)|(1<<OCR2AUB)|(OCR2BUB)|> (1<<TCR2AUB)|(1<<TCR2BUB));
Ja, so in etwa.
1
while(ASSR&((1<<TCN2UB)|(1<<TCR2BUB));
Michel Schl. schrieb:> 2. Okay der Timer hat mehrere Interrupts, sicher muss man dann alle> entsprechenden Flags löschen.> TIFR2&=~((1<<OCF2B)|(1<<OCF2A)|(1<<TOV2))
Das löscht aber keines der Flags.
Oh ja richtig, dass die Flags mit einer 1 gelöscht werden, habe ich
mehrfach gelesen. peinlich
Vielen Dank für eure schnelle und hilfreiche Unterstützung.
> Der Datenblatttext(siehe post Krapao) zu Bit6(EXCLK) des ASSR bleibt für> mich dennoch missvertändlich, da zum Einen davon gesprochen wird, dass> das Bit logisch 1 sein soll im asynchronen Modus um den Uhrquarz> betreiben zu können, zum Anderen der letzte Satz "Note that the crystal> Oscillator will only run when this bit is zero." oder ist hiermit der> Quarz an XTAL gemeint???
Stimmt doch nicht. Dort ist deutlich entweder von clock oder crystal
die Rede und dazwischen steht ein instead
D.h. man kann Timer2 entweder
1/ asynchron takten und an TOSC1 eine external clock hängen, also ein
externes Taktsignal. Dann muss Bit EXCLK 1 gesetzt werden.
oder
2/ asynchron takten und an TOSC1 und TOSC2 einen external crystal
(Uhrenquarz) hängen. Dann muss Bit EXCLK 0 gesetzt werden.
oder
3/ synchron mit dem Haupttakt takten und TOSC1 und TOSC2 werden nicht
benutzt und sind normale IO-Pins.