CTC bei ATTINY2313 8 Bit Timer0

OP #487612
Lesenswert?

Hallo
Ich bekomme mein Timer0 mit dem CTC nicht zum laufen. Kann mir jemand 
sagen wo hier das Problem ist. Laut Datenblatt sind die Register und der 
Interrupt-Vector richtig wenn ich es verstanden habe :)
Der Port B sollte nach ~ 7,8 sek auf 1 gehen.

#define F_CPU 4000000UL

#include <stdio.h>
#include <avr\io.h>
#include <avr\interrupt.h>

int Teiler;


// ISR( TIMER0_OVF_vect )   // Interrupt Overflow Aufruf Timer 0

ISR( TIMER0_COMPA_vect )   // Interrupt Compare A Aufruf Timer 0
{
  Teiler++;
  if( Teiler == 1000 )
  {
    Teiler = 0;
    PORTB = 0xFF;
  }
}


int main()
{
  DDRB = 0xff;     // Setze Port B als Ausgang
  PORTB = 0x00;    // Port B auf 0 setzen

  Teiler = 0;

  TCCR0A |= (1<<WGM01);        // Aktiviere CTC zum OCR0A Werte vorgeben
  TCCR0B |= (1<<CS00 | 1<<CS02);   // Setze Counter 0 prescaler 1024
  TIMSK |= (1<<TOIE0);        // Aktiviere Overflow Interrupt für 
Counter 0
  OCR0A = 128;                     // Wert für CTC

  sei();                 // Aktiviere Interrups allgemein

  while( 1 )
  {
  }
}
OP #487645
Lesenswert?

Axel Rühl wrote:
> kannnicht
>
>>  TIMSK |= (1<<TOIE0);        // Aktiviere Overflow Interrupt für
>
> Du musst den Comparematch Interrupt aktivieren
>
> Gruß
> /XlR.


Upps, danke das wars. Hatte davor den Timer mit Overflow versucht und 
das total übersehen. Mir fehlt aber auch noch ein bisschen die 
Erfahrung. Sind momentan meine ersten Versuche.

Ab wann muss man den seine Variablen mit "volatile" deklarieren ?

Gruss  Thomas
#487667
Lesenswert?

> Ab wann muss man den seine Variablen mit "volatile" deklarieren ?

volatile musst du dann nehmen, wenn Gefahr besteht, dass
der Compiler einen Zugriff auf die Variable wegoptimieren
könnte. Grob gesagt: Immer dann, wenn es für den Compiler
nicht ersichtlich ist, dass eine Variable auf anderen
Wegen als die die dem Compiler bekannt sind einen neuen
Wert kriegt.

volatile macht nichts anderes, als einfach nur mögliche
Optimierungen auf dieser Variablen abzuschalten.

Bsp:

du hast folgende Schleife

unsigned char i;
unsigned char a;

void foo()
{
   i = 0;

   while( i == 5 ) {
      a = 8;
   }
}

Wenn der Compiler diese Funktion übersetzt, dann findet die
Datenflussanalyse heraus, dass i zu Beginn der Schleife
den Wert 0 hat. Weiters findet die Analyse heraus, dass
es innerhalb der Schleife keine Möglichkeit für i gibt,
je verändert zu werden. Da i daher immer den Wert 0 hat,
kann die Schleife niemals betreten werden und kann damit
komplett wegfallen.

Nur: Jetzt kommt dein Programmund installiert einen Interrupt-
handler, welcher - Überraschung - sehr wohl i irgendwann mal
auf 5 setzt.

Nur: Das weis der Compiler nicht, wenn er foo() übersetzt.

Also muss man ihm mitteilen: Spar dir Optimierungen, die über
i laufen. i ändert seinen Wert auf Wegen die für dich nicht
einsehbar sind.

Und genau das macht das volatile

volatile unsigned char i;

Jetzt trifft der Compiler keinerlei Annahmen mehr über i.
Er speichert den Wert der Variablen auch nicht in einem
CPU Register zwischen, wie zb hier:

    j = i + i;

sondern liest bei jeder Erwähnung von i den Wert tatsächlich
aus dem Speicher aus. (Im obigen wäre das ja eigentlich unsinnig.
Speicher auslesen kostet Zeit. Wenn der Compiler i einmal holt
und dann verdoppelt kommt das gleiche raus)

Leider verkommt volatile bei vielen Programmierern zu:
Wenn du in einem ISR eine Variable benutzt, muss diese
volatile sein.
Unsinn. Jetzt weist du was wirklich dahinter steckt.

In deinem Pgm hast du den Fall aber nicht, selbst wenn
der ISR-Vektor richtig gestellt ist. Da Teiler eine globale
Variable ist, wird die vom Compiler sowieso mit 0 initialisiert.
Die Zuweisung von 0 in main() bewirkt also im Grunde genommen
gar nichts. Damit kommt Teiler aber nur noch in der ISR vor
und damit besteht die Gefahr gar nicht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren