Forum: Mikrocontroller und Digitale Elektronik CTC bei ATTINY2313 8 Bit Timer0


von Thomas W. (ram99)


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

von Otto (Gast)


Lesenswert?

Hallo Thomas,

das "volatile" für "Teiler" fehlt z.B.

Gruss Otto

von Thomas W. (ram99)


Lesenswert?

Otto wrote:
> Hallo Thomas,
>
> das "volatile" für "Teiler" fehlt z.B.
>
> Gruss Otto

Hallo Otto,
habe jetzt "volatile int Teiler;" eingefügt aber es möchte noch immer 
nicht funktionieren.

Gruss Thomas

von Axel R. (Gast)


Lesenswert?

kannnicht

>  TIMSK |= (1<<TOIE0);        // Aktiviere Overflow Interrupt für

Du musst den Comparematch Interrupt aktivieren

Gruß
/XlR.

von Thomas W. (ram99)


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

von Karl H. (kbuchegg)


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.

von the_devil (Gast)


Lesenswert?

@Karl heinz Buchegger

Danke, eine bessere Erklärung für "voaltile" habe ich no nie 
bekommen....
Respekt

von the_devil (Gast)


Lesenswert?

ähhh...volatile

von Reedemer (Gast)


Lesenswert?

Tach ich bin Hier neu und Wollte Fragen wie ich meinen Counter Aktiviere 
also das man ihn sieht und er auch schön Zählt

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.