Timer0 zählt nicht!

OP #2038600
Lesenswert?

Hi Leutz bin noch ziemlich frisch auf dem Gebiet. Meine Frage: Wieso 
zählt der TCNT0 nicht hoch oder sieht Jemand einen Fehler im Code.

Ich benutze einen Atmega8 mit 4.000 MHz



#include <avr/io.h>

int takt;
int sekunde;

void setup (void)
{
  TCCR0 |= ( 1<<CS02 )|( 1<<CS00 ); //counter0,Prescaler CK/1024
  TIMSK |= ( 1<<TOIE0 );       // enable counter0 overflow interrupt
  TCNT0 = 0x00;           // Counter0 auf Null setzen

  takt = 0;              // 4.000.000  1024  256 = 15
  sekunde = 0;
}

void aus (void)
{
   if(TCNT0 == 0xFF)
  {
    TCNT0 = 0x00;
    takt++;

    if (takt == 15)
    {
      sekunde++;
      takt = 0;
    }

    if(sekunde == 1)
    {
      sekunde = 0;

      if(PORTB == 0x01)
      {
        PORTB = 0x00;
      }

      else
      {
        PORTB = 0x01;
      }

    }

  }
}

int main (void)
{

  setup();
  DDRB = 0xFF;;
  while(1)
  {
    aus();
  }
}
Angehängte Dateien:
Persönliche Seite #2038611
Lesenswert?

In dem Programm sind mehrere Probleme, die nicht da wären, wenn du dir 
das Tutorial zum Timer genau angesehen hättest.

Du hast kein echtes Timer-Programm. Du schaltest zwar den enable 
counter0 overflow interrupt ein, hast aber keine Interrupt Service 
Routine ISR dafür.

Und du schaltest die Interrupts nicht global mit sei() frei. Zum Glück, 
denn wegen der fehlenden ISR würde das Programm abstürzen.

In der aus() fragst du TCNT0 auf 0xFF ab.

Es kann passieren, dass deine Aufrufe von aus() langsamer sind als der 
Timer0 zählt. Dann ist es Zufall mal TCNT0 == 0xFF zu erwischen.

Oder die Aufrufe von aus() sind wesentlcih schneller als der Timer0 
hochzählt. Dann erwischst du TCNT0 mehrfach im Zählzustand 0xFF.

Abhilfe ist exakt dann einen Interrupt auszulösen, wenn der Timer0 
Zähler von 0xFF auf 0x0 wechselt - die ISR eben.
#2038614
Lesenswert?

Deine LED (oder was auch immer du an dem Port Pin angeschlossen hast) 
blinkt mit rund 1kHz. Ich denke nicht, dass du das sehen wirst.


Dein Programm .... es ist zwar unorthodox und du hast da ein paar Dinge, 
die man so nicht macht, aber richtiger Fehler ist da erst mal keiner 
drinn. Du hast die (schlummernden) Fehler alle mit eventuell ein wenig 
Glück erfolgreich umschifft.

Du hast zwar den Overflow Interrupt freigegeben, hast aber keine ISR 
dafür. Da du die Interrupts nicht mittels sei generell freigegeben hast, 
passiert da also nichts.

Einen TCNT0 direkt abfragen bedeutet, dass die Abfrage schneller sein 
muss, als der Timer zählt, damit du den Zählerstand genau erwischt. Da 
du einen Vorteiler von 1024 hast, wird das in deinem Fall sogar der Fall 
sein.

Und da du den Timer händisch auf 0 zurücksetzt, kriegst du den 
Zählerstand von 0xFF tatsächlich auch nur 1 mal mit.

All das sind eigentlich No-No's. Allerdings wirken sie sich momentan 
(noch) nicht aus.
OP #2038683
Lesenswert?

so hab das Programm bischen verändert aber das funktioniert irgend wie 
nicht.

Meine Rechnung:
    MHz    Vorteiler   8-Bit-Timer = Overflows pro Sekunde
4.000.000  1024        256         = 15

bei der Simulation habe ich Festgestellt das er die ganze Zeit in der 
ISR bleibt. Wieso???


#include <avr/io.h>
#include <avr/interrupt.h>


int sekunde;


void setup (void)
{
  TCCR0 |= ( 1<<CS02 )|( 1<<CS00 ); //counter0,Prescaler auf 1024
    TIMSK |= ( 1<<TOIE0 );      //counter0 overflow interrupt
    TCNT0 = 0x00;        //Counter0 auf Null setzen
  sei();          //Interrupts global aktivieren
}


ISR(TIMER0_OVF_vect)
{

sekunde ++;

}


int main (void)
{
  DDRB = 0xFF;
  setup();
  while(1)
  {
    if(sekunde >= 15)
    {
      sekunde = 0;
      if(PORTB == 0x01)
      {
        PORTB = 0x00;
      }
      else
      {
        PORTB = 0x01;
      }
    }
  }
}

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