mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer zählt zu langsam


Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abend zusammen,

ich schmore gerade über folgendem Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "lcd-routines.h"
#include <stdlib.h>

 
//Variablen für die Zeit
volatile unsigned int  millisekunden=0;
volatile unsigned int  sekunde=0;

int main(void)
{
  TCCR2 =(1<<WGM21) | (1<<CS00) | (1<<CS01);    //Prescaler 64 / OCR0 125: 8MHz:64:125 = 1KHz
  OCR2=125;
  TIMSK|=(1<<OCIE2);
  sei();                          //3)Interrupts aktivieren

   while(1)
   {
   }
 
   return 0;
}
 
ISR (TIMER2_COMP_vect)              //4)Führe diese ISR bei Overflow von TCNT0 aus
{
  millisekunden++;
  if (millisekunden == 1000)
  {
    sekunde ++;
    millisekunden = 0;
  }
  // ... umwandeln siehe FAQ Artikel bei www.mikrocontroller.net
  // WinAVR hat eine itoa()-Funktion, das erfordert obiges #include <stdlib.h>
  char Buffer_ms[20]; // in diesem {} lokal
  itoa( millisekunden, Buffer_ms, 10 ); 
  // ... ausgeben 
  char Buffer_s[20]; // in diesem {} lokal
  itoa( sekunde, Buffer_s, 10 ); 
  // ... ausgeben 
  lcd_init();
  set_cursor(7,1);
  lcd_string( Buffer_ms );
  set_cursor(0,1);
  lcd_string( Buffer_s );
}

und kann mir nicht erklären warum der zu langsam zählt.

Taktfrequenz ist 16MHz, fuses dafür sind gesetzt.
Eigentlich sollte es ja laut der Formel:
16 000 000  64  250 = 1000
in einer sekunde 1000 interrupts geben. und da 1sec = 1000ms sollte des 
j stimmen...

kann mir vll jemand helfen?

Mfg, Pat

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  lcd_init();
  set_cursor(7,1);
  lcd_string( Buffer_ms );
  set_cursor(0,1);
  lcd_string( Buffer_s );
Das alles in einem Interrupt?
Wie lange dauert denn z.B. lcd_init()?
Sowas gehört in die leere while(1)-Schleife  :-o

Autor: HerrBrause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCCR2 =(1<<WGM21) | (1<<CS20) | (1<<CS21);

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wie lange dauert denn z.B. lcd_init()?
>Sowas gehört in die leere while(1)-Schleife  :-o

lcd_init() gehört nicht unbedingt in die while(1) ;)

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau nochmal genau hin. Die Formel im Datenblatt beschreibt etwas 
anderes (nicht Interrupts pro Sekunde), deshalb hast du einen 
Fehlerfaktor von 2 drin.

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
thx für die schnelle Hilfe, nun gehts habs noch n bissle mehr 
abgeändert.^^
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "lcd-routines.h"
#include <stdlib.h>

 
//Variablen für die Zeit
volatile unsigned int  millisekunden=0;
volatile unsigned int  sekunde=0;

int main(void)
{
  TCCR2 =(1<<WGM21) | (1<<CS20) | (1<<CS21);    //Prescaler 64 / OCR0 125: 8MHz:64:125 = 1KHz
  OCR2=250;
  TIMSK|=(1<<OCIE2);
  sei();                          //3)Interrupts aktivieren

   while(1)
   {
   }
 
   return 0;
}

void anzeigen (void)
{
    // ... umwandeln siehe FAQ Artikel bei www.mikrocontroller.net
  // WinAVR hat eine itoa()-Funktion, das erfordert obiges #include <stdlib.h>
  char Buffer_ms[20]; // in diesem {} lokal
  itoa( millisekunden, Buffer_ms, 10 ); 
  // ... ausgeben 
  char Buffer_s[20]; // in diesem {} lokal
  itoa( sekunde, Buffer_s, 10 ); 
  // ... ausgeben 
  lcd_init();
  set_cursor(7,1);
  lcd_string( Buffer_ms );
  set_cursor(0,1);
  lcd_string( Buffer_s );
}

ISR (TIMER2_COMP_vect)              //4)Führe diese ISR bei Overflow von TCNT0 aus
{
  millisekunden++;
  if (millisekunden == 1000)
  {
    sekunde ++;
    millisekunden = 0;
  }
  if(millisekunden % 100 == 0)
  {
  anzeigen();
  }
}

Autor: MeinerEiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reicht es nicht, das LCD nur 1x beim Programmstart zu initialisieren?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wenn du es noch ein wenig korrekter machen möchtest, dann änderst du 
die 250 in 249.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nimm das lcd_init() aus anzeigen() raus und pack es vor diesen Befehl
in main():

  sei();                          //3)Interrupts aktivieren

Autor: Steffan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>anzeigen();

Gehört nicht in die ISR.

Autor: HerrBrause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo, nimm einen zweiten Timer und lass anzeigen() regelmäßig aufrufen.

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
achso also prakrisch durch den 2. Timer dann bestimmen wie oft die 
anzeige aktualisiert wird?

edit:  hab nu die Änderungen ( bis auf das mit der anzeigen funktion) 
vorgenommen aber jetzt ist der irgendwie zu schnell????

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> nimm einen zweiten Timer
Wenn anzeigen() gerade ausgeführt wird, und länger als 1 ms dauert, dann 
hilft auch ein zweiter Timer nichts...

Richtigerweise wird lcd_init() genau 1 mal gemacht. Und dann in der 
Hauptschleife das anzeigen(). Für das Ausführen von anzeige() wird in 
der ISR ein Flag gesetzt.
Etwa so:
volatile char updateanzeige;
:
main () {
   while(1)
   {
     if (updateanzeige) {
        anzeigen();
        updateanzeige=0;  // fertig, Flag löschen
     }
   }

}
:
ISR (TIMER2_COMP_vect)              //4)Führe diese ISR bei Overflow von TCNT0 aus
{
  if (millisekunden == 1000)
  {
    sekunde ++;
    millisekunden = 0;
  }
  if(millisekunden % 100 == 0)
  {
    updateanzeige=1;  // Flag setzen
  }
}

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick R. schrieb:
> edit:  hab nu die Änderungen ( bis auf das mit der anzeigen funktion)
> vorgenommen aber jetzt ist der irgendwie zu schnell????

Um welchen AVR geht es denn genau?
Beim Mega8 z.B. sind CS20+CS21 ein Teiler von 32 (und nicht 64).

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ah ok dann is klar warums net geht is nemmich genau der ^^. Tja das war 
wohl ein blick ins datenblatt zu wenig ^^ thx


edit: hab nu im datenblatt folgendes gefunden:
The prescaled clock has a frequency of either f/8, f/64, f/256 or f/1024

also müsse der doch stimmen...

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Patrick R. schrieb:

> edit: hab nu im datenblatt folgendes gefunden:
> The prescaled clock has a frequency of either f/8, f/64, f/256 or f/1024

Jede Wette, das Zitat stammt aus den Kapitel:
Timer/Counter0 and Timer/Counter1 Prescalers
(du verwendest Timer2)

Kann hier aber keiner wirklich kontrollieren, da wir ja immer noch nicht 
wissen, welcher AVR.

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab vorher das geschrieben:
>ah ok dann is klar warums net geht is nemmich genau der<
-> also n ATmega8

hab den code nun überarbeitet und (1<<CS22) gesetzt, nun zählt er im 
richtigen tempo ^^

Vielen Dank nochmal für eure hilfe

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, das "is nemmich genau der" hatte ich übersehen.

Autor: Patrick R. (pat711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
war au leich zu übersehn ^^ sry nächstes mal machichs deutlicher

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.