Autor Thema: Timer0 bei PIC18F2620 - Ungenaue Durchlaufzeit??  (Gelesen 797 mal)

Offline Monika

  • Newbie
  • *
  • Beiträge: 32
    • Profil anzeigen
Timer0 bei PIC18F2620 - Ungenaue Durchlaufzeit??
« am: Januar 08, 2018, 16:28:25 Nachmittag »
Hallo,

ich arbeite seit Jahren mit dem PIC18F2620 und alle "normalen" Anwendungen von Timer0, auch in Kombination mit anderen Interrupts, verhalten sich meistens so, wie ich es mir erwarte.

Heute steht allerdings ein eher zeitkritisches Projekt an, das einige Verständnisfragen aufwirft.

Kurz zum Ablauf:
Abhängig von einem Potentiometer sollen Impulse mit einer Frequenz von 100 - 15750Hz ausgegeben werden.

Da ich mir nicht sicher war, wie sich der PIC bei so hohen Ausgangsfrequenzen verhält, habe ich damit begonnen, das 15750Hz-Signal zu erzeugen:

(Insert Code funktioniert leider nicht!)
void highprio_int(void)
{
   if(INTCONbits.TMR0IF)
   {
      INTCONbits.TMR0IF = 0;
      WriteTimer0(timer_startwert);
      
      AUSGABE_PIN = 1;  //Impulsausgabe
      AUSGABE_PIN = 0;
      
      laufvariable1++;
      laufvariable2++;      
   }
}

Den Timer-Startwert habe ich mir mit 65028 berechnet, allerdings stimmt dann die Ausgangsfrequenz nicht, sondern es wird ein Wert von 65108 benötigt, damit ich mit dem Oszilloskop das richtige Ausgangssignal messe.
Das ist für mich auch noch relativ plausibel, da ja bei so einer kurzen Durchlaufzeit das Rein-/Rausspringen in die Interruptroutine ein nicht zu vernachlässigender Zeitfaktor ist.

Das Hauptprogramm ist sehr einfach gehalten: Nach jedem 270. Impuls soll mit dem ADC der Potentiometer-Wert eingelesen und dann die Frequenz gegebenenfalls angepasst werden.

void main(void)
{
   Init();                  // Funktionsaufruf für alle notwendigen Einstellungen

   while(1)      
   {   
      TESTPIN = 1;
   
      if(laufvariable1 >= 270)
      {
         laufvariable1 = 0;
         
         ConvertADC();
         while(BusyADC());

         //ADC_result = ReadADC();      
      }
      TESTPIN = 0;
   }
}

Die beiden Zeilen ConvertADC() und while(BusyADC()) ändern am Ausgangssignal nichts, aber sobald ReadADC() aufgerufen wird, ändert sich die Ausgangsfrequenz 15700Hz auf 15000Hz. Wenn dann noch die Berechnung für den Timer-Startwert aus dem ADC_result dazukommt, liegt die Frequenz überhaupt nur mehr bei 12kHz!
Mit Hilfe des Testpins kann ich nachmessen, dass das Hauptprogramm schnell genug läuft und ich noch lange nicht an der Grenze des Möglichen angelangt bin.

Ich hätte mir erwartet, dass bei jedem 270. Impuls irgendeine Verzögerung oder ähnliches auftritt, aber nicht, dass sich dadurch die gesamte Zeitbasis des Timers ändert!!! Wie kann das passieren? Ist das nicht die Definition des Timer-Interrupts, dass dieser immer zu einer voreingestellten Zeit aufgerufen wird und das restliche Programm in der verbleibenden Zeit dazwischen abgearbeitet wird?

Durch weitere Messungen habe ich noch versucht, die Ungenauigkeit genauer zu definieren und ich glaube, dass der größte Zeitfehler beim Zurückspringen von der Interruptroutine in das Hauptprogramm passiert. Ist diese Zeitspanne vielleicht davon abhängig, welche Variablen im Hintergrund gesichert werden müssen?

Hat jemand dafür eine Erklärung?

Vielen Dank,
Monika

 


* Recent Topics