Forum: Mikrocontroller und Digitale Elektronik ATmega88 - Timer2 OVF mittels Uhrenquarz - Probleme beim Konfigurieren


von Michel S. (11michi11)


Lesenswert?

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

von Krapao (Gast)


Lesenswert?

> 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.

von Krapao (Gast)


Lesenswert?

> 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.

von Michel S. (11michi11)


Lesenswert?

Hab es jetzt nochmal wie folgt geändert, aber es funktioniert nicht.
Könnte mir vlt. jemand helfen und mir meinen Fehler aufzeigen?!

ASSR   |= (1<<EXCLK);
DDRC   &= ~(1<<PC5);
DDRC   |= (1<<PC4);
PORTC  |= (1<<PC5)|(1<<PC4);
DDRD   &= ~(1<<PD3);
DDRD   |= (1<<PD1);
PORTD  |= (1<<PD3);
EICRA  |= (1<<ISC11);
EIMSK  |= (1<<INT1);
lcd_init();
lcd_clear();
adc_init();
TIMSK2 &=(~(1<<TOIE2)|(1<<OCIE2A)|(1<<OCIE2B));
ASSR   |= (1<<AS2);
TCCR2B |= (1<<CS22)|(1<<CS20);
TCNT2  = 0x00;
TIMSK2 &=(~(1<<TOIE2)|(1<<OCIE2A)|(1<<OCIE2B));
TIMSK2 |= (1<<TOIE2);
sei();

von Karl H. (kbuchegg)


Lesenswert?

rein aus formalen Gründe (also ohne dass ich ins Datenblatt oder nach 
dem Sinn gefragt habe) kann das hier
1
TIMSK2 &=(~(1<<TOIE2)|(1<<OCIE2A)|(1<<OCIE2B));

nicht richtig sein. Ich vermute du wolltest die ~ vor dir Klammer haben. 
So jeden Falls ist das ein unlogisches Statement. Was soll es bewirken?

von Stefan E. (sternst)


Lesenswert?

1
ASSR   |= (1<<EXCLK);
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?

von Michel S. (11michi11)


Lesenswert?

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);

von Martin H. (martin_h85)


Lesenswert?

Guten Tag,

Hier mal ein Code Schnipsel den ich aktuell verwende, der auch 
funktioniert :
1
// Timer2 konfigurieren
2
ASSR   = (1<< AS2);                            // Timer2 asynchron takten
3
long_delay(1000);                               // Einschwingzeit des 32kHz Quarzes
4
TCCR2A = (1<<WGM21) | (1<<WGM20);               // Fast PWM, non inverted      
5
TCCR2A  &= ~(1<<COM2A1) | (1<<COM2A0);
6
TCCR2B = (1<< CS20);                            
7
OCR2A  = 128;                                   // Tastverhältnis 50%
8
while((ASSR & (1<< TCR2BUB)));         // Warte auf das Ende des Zugriffs
9
TIFR2  &= ~(1<<TOV2);                     // Interrupts löschen
10
TIMSK2 |= (1<<TOIE2);                     // Timer overflow Interrupt freischalten   
11
sei();

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

von Uwe (Gast)


Lesenswert?

ASSR->EXCLK muß 0 sein und ASSR->AS2 auf 1 ... fertisch.

von Michel S. (11michi11)


Lesenswert?

Danke für eure schnelle Unterstützung, werde ich heute noch ausprobieren 
und mal sehen, ob es dann funktioniert.
Anderfalls "nerv" ich nochmal ... ;)

von Stefan E. (sternst)


Lesenswert?

> 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.

von Michel S. (11michi11)


Lesenswert?

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))

von Uwe (Gast)


Lesenswert?

> 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 !

von Stefan E. (sternst)


Lesenswert?

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.
1
TIFR2 = (1<<OCF2B) | (1<<OCF2A) | (1<<TOV2);

von Michel S. (11michi11)


Lesenswert?

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.

von Krapao (Gast)


Lesenswert?

> 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.

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.