www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer passt nicht zu Simulation, Timer nicht genau


Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte für mein Programm auf einem Atmega168 mit 16 MHz Quarz ein 
vorgeschriebene Programmlaufzeit einrichten.
Dafür verwende ich einen 8-Bit Timer wie im Code s.u. zu sehen. Das 
Programm läuft in der Simulation genau so wie es sein soll, ein 
Programmdurchlauf dauert genau 0,1ms bzw. 1ms (je nach Divisor).

16.000.000/8 = 2.000.000 --> zähler bis 200 ergibt 0,1ms pro Durchlauf
bzw.
16.000.000/64 = 250.000 --> zähler bis 250 ergibt 1ms pro Durchlauf

Unglücklicherwiese ist die Programmlaufzeit auf dem Controller DEUTLICH 
größer! Woran kann das liegen?!? Hab ich bei dem Prescaler etwas falsch 
verstanden?!

Hier mein Code:

main.c:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <general.h>

int main(void) 
{
  sei();          //Globale Interrupts aktivieren
  initPorts();    //Funktionen der Ports definieren
  initTimer8(0);  //Timer starten

  int a = 0;

  while(1)
  {
  
    if(a==1000)            //nach 100ms
    {
      PORTB = 0x04;  //Leuchtdiode ein
    }
    
    if(a==2000)            //nach 100ms
    {
      PORTB = 0x00;  //Leuchtdiode aus
      a=0;
    }

    a++;
        
    while(isTimerRunning(0)==0){}
  }
  return 0;
}


und hier der Timer:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <general.h>

volatile BYTE gbTimerIrqFlag0=0;  //Globale Variable für Interrupt-Flag
volatile BYTE gbTimerIrqFlag2=0;  //Globale Variable für Interrupt-Flag


void initTimer8(BYTE bNr)     //Timer initialisieren, Übergabe Nummer des Timers bNr 

{
    switch(bNr)               //Ansprechen des gewählten Timers
          
    {
    case 0 :      //Timer 0,1ms
      
    TCCR0A=0x02;    //Output-Compare-Pin aus, kein PWM, Timer-Typ: CTC
    TCCR0B=0x02;  //Timer auf Taktrate 2 MHz setzen (Teiler auf 8)
    TCNT0=0x00;  //Zähler Register auf 0 setzen
    OCR0A=200-1;  //Vergeich des Timers mit vorgegebenen Wert: Laufzeit 0,1ms
    OCR0B=0x00;  //Compare-Register B wird nciht verwendet
    TIMSK0=0x02;  //OCR0A-Interrupt ein, Overflow- und OCR0B-Interrupt aus

    break;

    case 2 :      //Timer 1ms
      
    
    TCCR2A=0x02;  //Output-Compare-Pin aus, kein PWM, Timer-Typ: CTC
    TCCR2B=0x03;  //Timer auf Taktrate 250 kHz setzen (Teiler auf 64)
    TCNT2=0x00;  //Zähler Register auf 0 setzen
    OCR2A=250-1;  //Vergeich des Timers mit vorgegebenen Wert: Laufzeit 1ms
    OCR2B=0x00;  //Compare-Register B wird nciht verwendet
    TIMSK2=0x02;  //OCR2A-Interrupt ein, Overflow- und OCR2B-Interrupt aus

    break;
  }

}



BYTE isTimerRunning(BYTE bNr)  //Funktion zum Feststellen, ob vorgegebene Zeit abgelaufen 
{
  BYTE bReturn=0;

  switch(bNr)    //Ansprechen des gewählten Timers
  {
  
  case 0 :
    bReturn=gbTimerIrqFlag0;  //Solange die OCR-Flag nicht gesetzt ist bleibt die Rückgabe 0, anderenfalls wird sie 1
    gbTimerIrqFlag0=0;    //OCR-Flag zurücksetzen

    break;
  
  case 2 :
    bReturn=gbTimerIrqFlag2;  //Solange die OCR-Flag nicht gesetzt ist bleibt die Rückgabe 0, anderenfalls wird sie 1
    gbTimerIrqFlag2=0;    //OCR-Flag zurücksetzen
    break;
  
  }

  return bReturn;

}



ISR(TIMER0_COMPA_vect)          //Interrupt-Behandlung Timer 0
{    

  gbTimerIrqFlag0=1;  //OCR-Flag setzen, wenn Interrupt ausgelöst

}

ISR(TIMER2_COMPA_vect)          //Interrupt-Behandlung Timer 2
{    

  gbTimerIrqFlag2=1;  //OCR-Flag setzen, wenn Interrupt ausgelöst

}

Autor: Magnus M. (magnetus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Carsten schrieb:
> Unglücklicherwiese ist die Programmlaufzeit auf dem Controller DEUTLICH
> größer!

Kannst du "DEUTLICH größer" in Zahlen ausdrücken?

> Woran kann das liegen?!?

Dein Controller läuft nicht mit den von dir angenommenen 16MHz.

Gruß,
Magnetus

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Grob gestoppt sind es ca. 1,7 statt der erwarteten 0,1 sekunden!!

Mit welcher geschwindigkeit läuft denn der Controller... bei dem 
verhältnis würde ich vermuten dass der nur auf 1 MHz läuft, aber warum 
?!

Autor: ElektroMaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Standard-Taktquelle ist ein interner RC-Oszillator.

So lange du den Chip nicht so umkonfigurierst, dass er mit einer 
externen Taktquelle zusammenarbeitet, läuft der Chip mit den internen 
1MHz (Stichwort: Fuse-Bits, aber GRÜNDLICH lesen!)

Autor: Magnus M. (magnetus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Carsten schrieb:
> Grob gestoppt sind es ca. 1,7 statt der erwarteten 0,1 sekunden!!

Das wäre dann Faktor 17.

> Mit welcher geschwindigkeit läuft denn der Controller... bei dem
> verhältnis würde ich vermuten dass der nur auf 1 MHz läuft,

Richtig

> aber warum?!

Siehe Beitrag von ElektoMaus.

Gruß,
Magnetus

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
17 wäre es bei einer genauen Messung, aber 16 wird ja vermutlich eher 
passen, da die controller vermutlich nicht auf 941.176 Hz laufen.

Mit den Fuse Bits ist das beim AVR-Studio ja recht komfortabel 
gestaltet, dort kann man ja einfach den externen Quarz wählen... nun ist 
aber die Frage, welchen ich denn nehme, für einen 16MHz Quarz, es gibt 
dor ja viele zur auswahl!
Klar ist natürlich einer mit 8-...MHz, alle anderen sind langsamer, aber 
was hat es mit dem "Reset" auf sich... leider kann man die unteren 
auswahlmöglichkeiten im AVR-Studio nicht mehr ganz lesen!

Wenn mir das eben jemand sagen könnte, wäre super!

Ja, ich weiß, ich kann jetzt auch 3 Stunden danach googlen und finde es 
evtl. dann auch...

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmm, mit dem
"Ext. Crystal Osc.; Frequency 8.0-   MHz; Start-up time PWRDWN/RESET: 
16K CK/14CK + 65 ms; [CKSEL=1111 SUT=11]"

funktioniert es jedenfalls, allerdings komme ich jetzt auf 0,7s statt 
0,1s... was passt denn da nicht ?!?!

Autor: Magnus M. (magnetus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Carsten schrieb:
> funktioniert es jedenfalls, allerdings komme ich jetzt auf 0,7s statt
>
> 0,1s... was passt denn da nicht ?!?!

CKDIV8 Fuse.

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
CKDIV8 Fuse ist gestzt, also im AVR-Studio ein Haken dran... soll das 
ding gesetzt sein, oder nicht ?!

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aha, alles klar, wird geteilt durch 8... soll natürlch nicht!!

jetzt funktionierts... naja, besser... nun zeigt er nach 1minute nur 46 
sekunden an!

Aber trotzdem schonla danke!!

Noch ne idee, wo diese restabweichung herkommen könnte?!

Autor: Remote One (remote1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Magnus M. (magnetus) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
By the way:
int main(void) 
{
  sei();          //Globale Interrupts aktivieren
  initPorts();    //Funktionen der Ports definieren
  initTimer8(0);  //Timer starten

Das sei(); solltest du lieber hinter die Initialisierung setzen.

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.