Autor Thema: Timer Preload bei PIC18  (Gelesen 4676 mal)

Offline Oliver

  • Newbie
  • *
  • Beiträge: 4
    • Profil anzeigen
Timer Preload bei PIC18
« am: Juli 20, 2009, 11:12:24 Vormittag »
Hallo Leute,

bin neu beim PIC18 und auch neu hier. Somit erst einmal Hallo und vorab danke für Ideen und Tips.

Derzeit streite ich mich hier mit einem PIC18F97J60 und dem Timer1 rum. Das Ziel war es einen sauberen 1ms Single-Shot Interrupt hinzubekommen. Eigentlich kein Ding, offensichtlich aber doch.

Der PIC läuft mit externen 25MHz für den Ethernet-Controller. Durch PLL (Konfiguration überprüft) bekomme ich intern 41,6667MHz. Dank 1:4 Prescaler für Peripherie und 1:2 Prescaler bei Timer1 (T1CON = 0x90), habe ich mir für 1ms 5208 Zählschritte ausgerechnet. Somit ist mein Preload-Wert für den Timer 0x10000 - 5208.

Leider bekomme ich aber laut Oskar nun 1.026ms heraus, was zu deutlich daneben liegt.

Ein Versuch mit einem periodischen Timer1-Interrupts (LED1 toggle, Reload in der ISR und T1 anschließend starten) brachte die gleiche Abweichung von 1.026ms. Witzigerweise zeigte ein Versuch ohne Preload, also durchlaufend, eine Frequenz von 39,7349Hz, was ziemlich genau dem erwarteten Wert entspricht. Die Abweichung beträgt weniger als 40ppm, was der Toleranz des Quarzes entspricht.

Hat jemand eine Idee, woher dies kommt? Starte ich den Timer falsch? Habe ich einen Fehler im Berechnen des Preload-Wertes?

void t1Init(void)
{
  uiTimerPreset = (0xFFFF - 5208) + 1;
  IPR1bits.TMR1IP = 0;    // Low priority
  PIE1bits.TMR1IE = 0;    // Overflow Interrupt disabled

  // Timer off, 16-bit, internal timer, 1:2 prescalar
  T1CON = 0x90;
}

void t1Shot(void)
{
  // Timer1 stop
  T1CONbits.TMR1ON = 0;

  // Preload
  TMR1H = (BYTE)(uiTimerPreset >> 8);
  TMR1L = (BYTE)uiTimerPreset;

  // Enable Timer1 OVF
  PIR1bits.TMR1IF = 0;
  PIE1bits.TMR1IE = 1;

  /* @DEBUG */
  LED1_IO = 1;

  // Start Timer1
  T1CONbits.TMR1ON = 1;
}

void t1ISR(void)
{
  if(PIR1bits.TMR1IF)
  {
    // @DEBUG
    LED1_IO = 0;

    // Timer1 stop
    T1CONbits.TMR1ON = 0;

    // Clear Timer1 OVF IRQ flag
    PIR1bits.TMR1IF = 0;
  }
}

Offline Master Snowman

  • Sr. Member
  • ****
  • Beiträge: 293
    • Profil anzeigen
    • You never know until you go
Re: Timer Preload bei PIC18
« Antwort #1 am: Juli 20, 2009, 12:21:17 Nachmittag »
hallo & herzlich willkommen

ich habe nicht alles durchgerechnet und die register angeguckt, ob alles i.o. ist, was aber bei so genauen timer-interrupts wichtig ist: die zeit, bis der interrupt an sich überhaupt abgearbeitet wird, als auch die zeit, bis deine LED toggelt.. ggf. müsstest du im assembler-listing gucken, wieviele befehle im interrupt abgearbeitet werden bis deine LED toggelt plus (wenn ich mich nicht irre) 6 befehle für das verlassen des hauptprogramms und einsteigen in die interrupt-routine.

grüsse
Emanuel

Offline Oliver

  • Newbie
  • *
  • Beiträge: 4
    • Profil anzeigen
Re: Timer Preload bei PIC18
« Antwort #2 am: Juli 21, 2009, 13:41:44 Nachmittag »
Ne, dass ist es leider nicht. Hab mir schon den Interrupt disassembliert angeschaut. Es würde mich wundern, wenn der PIC bei internen 41,67MHz ganze 26µs für das Schreiben des Zählerregisters benötigt. Ich hab es auch mit einem konstanten Wert ausprobiert, leider keine Verbesserung.

Offline Stampede

  • Hero Member
  • *****
  • Beiträge: 1026
    • Profil anzeigen
    • PicPlayer.de
Re: Timer Preload bei PIC18
« Antwort #3 am: Juli 21, 2009, 15:02:51 Nachmittag »
Hi,

die Werte (Preset) scheinen OK. Poste mal das Disassembly, und schau im DB, wie lange die Latenz für den ISR ist (glaube so 4Takte.
Möglicherweise baut der C18 aber auch das Workaround für den Timer1 Bug ein (eigentlich nur für asynchonen Betrieb), der knapp 31µs dauert:
http://ww1.microchip.com/downloads/en/DeviceDoc/80329a.pdf
Versuche doch mal einen anderen Timer, z.B Timer3!


Gruß
Stefan

Offline Bernd

  • Hero Member
  • *****
  • Beiträge: 3820
    • Profil anzeigen
Re: Timer Preload bei PIC18
« Antwort #4 am: Juli 21, 2009, 19:41:55 Nachmittag »
Zitat
Witzigerweise zeigte ein Versuch ohne Preload, also durchlaufend, eine Frequenz von 39,7349Hz

Damit kannst Du auf jeden Fall sicher sein, daß der Takt des PICs tatsächlich 41,667MHz ist und der Timer mit der vorab berechneten Rate inkrementiert.

Zitat
Starte ich den Timer falsch? Habe ich einen Fehler im Berechnen des Preload-Wertes?

Nein. Mit dem Simulator ist der Fehler wesentlich geringer (ca. 1,1µs mehr als die gewünschten 1ms bei deaktivierten Compilieroptimierungen und ca. 0,9µs mehr mit allen Optimierungen). Einen Fehler in dieser Größenordnung hätte ich auch erwartet (die Gründe dafür sind schon erwähnt worden).

Blöde Frage, aber anders kann ich mir eigentlich diese signifikante Abweichung nicht erklären: Könnte der um eine Zehnerpotenz größere beobachtete Fehler aus einem Meß- oder Ablesefehler resultieren?

Poste außerdem bitte mal ein vollständig kompilierbares Beispiel (ich mußte einige Sachen hinzufügen, um den Code zu testen). Sollte weiterer Code vorhanden sein, der für den Test nicht nötig ist, entferne ihn (auch für Deine Tests).

Zitat
Möglicherweise baut der C18 aber auch das Workaround für den Timer1 Bug ein (eigentlich nur für asynchonen Betrieb), der knapp 31µs dauert

Ich mache nicht viel mit dem C18, aber nach meinem Kenntnisstand berücksichtigt der C18 überhaupt keine Errata. Auf die schnelle habe ich auch keine Compileroptionen gefunden, welche ein Deaktivieren eventueller zeit- oder speicheraufwendiger Workarounds ermöglicht (diese Option müßte gegeben sein, falls der Fehler irgendwann behoben wird ;)).

Viele Grüße

Bernd

 


* Recent Topics