Forum: Mikrocontroller und Digitale Elektronik Timer läuft bei OCR=255, sonst nicht


von P.C. (Gast)


Lesenswert?

Ich habe folgendes Problem:

Der Timer 2 meines ATmega8 soll 500x pro Sekunde einen Interrupt 
auslösen.

CPU-Frequenz ist 4MHz (kein Teiler). Den Timer habe ich auf CTC Mode und 
Prescaler 32 gesetzt. Dann ergibt sich 4000000/32/500-1 = 249 (0xF9):
1
TCCR2 =  (1 << WGM21) | (0 << WGM20) | (0 << CS22) | (1 << CS21) | (1 << CS20);
2
OCR2 = 0xFF;

Ich habe die Testroutine auf eine LED heruntergebrochen, die im 
Sekundentakt blinken soll (toggle alle 250 Interrupts). Dazu frage ich 
das TOV2 Flag ab.

Setze ich OCR = 0xFF; funktioniert das auch (Zeit halt nicht perfekt, 
aber nah genug an 1s um das behaupten zu können), sobald ich es mit 0xF9 
(oder irgendeinem anderen Wert) versuche, scheint der Timer zu stehen, 
zumindest tut sich nichts mehr.

Exakt selbes Verhalten, wenn ich mit 1MHz/8 oder 8MHz/64 arbeite.

Wo könnte mein Fehler liegen?

von Klaus (Gast)


Lesenswert?

Da du schon dein ganzes Problem auf ein LED_Togglen runtergebrochen 
hast, kannst du uns den ganzen Code auch gerne zur Verfügung stellen, 
damit wir dir helfen können.

von Joe S. (bubblejoe)


Lesenswert?

Bitte ganzen Code. Interrupts global eingeschaltet?

von Falk B. (falk)


Lesenswert?

@ P.C. (Gast)

>Sekundentakt blinken soll (toggle alle 250 Interrupts). Dazu frage ich
>das TOV2 Flag ab.

Falsch. Beim CTC MOde muss man den OCx Interrupt nutzen.

von Stefan E. (sternst)


Lesenswert?

P.C. schrieb:
> Dazu frage ich
> das TOV2 Flag ab.

Und genau das ist dein Problem. Das ist das falsche Flag bei CTC.

von P.C. (Gast)


Lesenswert?

OK, hier:
1
#define F_CPU 4000000UL
2
3
int main(void) {
4
  DDRC = (1 << DDC1);
5
  TCCR2 =  (1 << WGM21) | (0 << WGM20) | (0 << CS22) | (1 << CS21) | (1 << CS20);
6
  OCR2 = 0xF9;
7
8
  sei();
9
10
  while (1) {
11
    if (TIFR & (1 << TOV2)) {
12
      TIFR |= 1 << TOV2;
13
      timerInterrupt();
14
    }
15
  }
16
  return 0;
17
}
18
19
void timerInterrupt(void) {
20
  static uint8_t counter;
21
  counter++;
22
  if(counter == 250) {
23
    PORTC ^= (1<<PC1);
24
    counter = 0;
25
  }
26
}

von P.C. (Gast)


Lesenswert?

Stefan Ernst schrieb:
> P.C. schrieb:
>> Dazu frage ich
>> das TOV2 Flag ab.
>
> Und genau das ist dein Problem. Das ist das falsche Flag bei CTC

Ja, OCF2 wäre wohl besser... Danke!

von Kaj (Gast)


Lesenswert?

P.C. schrieb:
1
TCCR2 = (1<<WGM21) | (0<<WGM20) | (0<<CS22) | (1<<CS21) | (1<<CS20);

Was soll da raus kommen, wenn du irgendwas mit 0 veroderst? außerdem 
kannst du eine 0 nicht schieben...

Grüße

von P.C. (Gast)


Lesenswert?

Dabei soll nichts herauskommen. Aber da ich mit einigen Einstellungen 
experimentiert habe und die 0 auch nicht weh tut, habe ich es zur 
Übersicht drin gelassen.

Da lag das Problem auch nicht, mti dem richtigen Interrupt Flag läuft 
das Programm nun und kann seine eigentliche Aufgabe leisten.

von ich (Gast)


Lesenswert?

Kaj schrieb:
> P.C. schrieb:TCCR2 = (1<<WGM21) | (0<<WGM20) | (0<<CS22) |
> (1<<CS21) | (1<<CS20);
>
> Was soll da raus kommen, wenn du irgendwas mit 0 veroderst? außerdem
> kannst du eine 0 nicht schieben...
>
> Grüße

Hi,

jedenfalls kommt kein Fehler raus, es kann nichts passieren.
Mathematisch gesehen ist das zwar Unsinn, das stimmt. Aber wenn man
eine Übersicht über alle Bits haben möchte, kann man das schon machen.
Sonst sieht man ja nur die Bits, die auf "1" stehen. Und so kann man
auch mal schnell ein Bit ändern, um Tests zu machen und braucht nichts
neu zu schreiben. Wenn man dann mit der Programmierung fertig ist,
kann man ja die "0<<" Ausdrücke rausschmeißen, der Schönheit halber.

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.