www.mikrocontroller.net

Forum: Compiler & IDEs Timer0 zählt nicht!


Autor: Andreas V. (andreas_v)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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();
  }
}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas V. (andreas_v)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK danke erstmal für die Tipps ich schau mir jetzt Erstmal das Tutorial 
an habe da etwas falsch verstanden denke ich.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> 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.

Hmm.
Da dürfte ich mich am Taschenrechner vertippt haben.
Erneutes nachrechnen bringt 1Hz zu Tage

4000000 / 1024  = 3906
3906 / 255 = 15
und dann noch durch 15  macht 1

Also das passt

Autor: Andreas V. (andreas_v)
Datum:

Bewertung
0 lesenswert
nicht 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;
      }
    }
  }
}

Autor: Mork (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe den Abschnitt 
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

volatile ist hier nämlich das Problem.

MfG Mark

Autor: Andreas V. (andreas_v)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Vielen dank es funktioniert einwandfrei.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Besser so, aber noch nicht einwandfrei :-)

Und jetzt nicht aufgeben, sondern im Artikel Interrupt nachlesen, 
was es mit atomaren Zugriff auf Variablen zu tun hat und wieso 
volatile allein nicht reicht.

Dann hast du dir einen Riesenbatzen AVR-Wissen angeeignet!

Autor: Andreas V. (andreas_v)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok danke das ist echt super hier man bekommt sehr schnell Hilfe.

bin jetzt dabei das AVR-GCC-Tutorial zu lesen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.