PIC24 Timer1

OP #3484470
Ich habe ein kleines Problem mit dem Timer1 des PIC24. Ich will alle 
500ms ein Interrupt haben und habe dazu den Prescaler auf 1:256 gesetzt:
16MHz/256=62500Hz
0.5s*62500Hz=31250
Also habe ich das Period Register auf 31250 gesetzt. Im Simulator 
bekomme ich alle 8.000.255 Zyklen einen Interrupt. Wenn ich das PR1 auf 
31249 setze sind es 7.999.999 Zyklen. Die 255 lassen vermuten, dass das 
irgendetwas mit dem 1:256 Prescaler zu tun hat. Gibt es einen Trick um 
genau auf die 0.5 Sekunden (8.000.000Zyklen) zu kommen?

Vielen Dank und Grüße
Max
Gast #3484532
Der Prescaler legt Deine kleinste Zeiteinheit fest die der Timer dann 
nur noch abzählt.
Ich hab jetzt wenig Lust mich wieder in die 24F timer einzulesen, aber 
wie wärs wenn Du eine kleinere Zeiteinheit nimmst die sich besser 
darstellen läßt und in der IRQ den Kram zusammenbastelst.

Wenns geht verschachtel zwei 16bit Timer zu einem 32bit und löse das 
Problem durch brachiale Recourcenverschwendung.
OP #3484536
Helmut S. schrieb:
> Wie misst du diese Zyklen?
MPLAB SIM, STOP WATCH
Setzt in der ISR einen Breakpoint starte die Simulation, setzt beim 
Break die Stop Watch auf null und Simuliere bis zum nächsten Breakpoint.

Helmut S. schrieb:
> Bedenke, dass der Interrupt erst ausgeführt wird, nachdem der gerade
> bearbeitete Befehl abgearbeitet wurde.
Der Fehler ist aber konstant und fällt weg, wenn ich relativ von einem 
Break zum anderen messe. An den Zahlen ändert sich auch nichts, wenn ich 
den Breakpoint ans Ende der ISR setze.
#3484545
> Helmut S. schrieb:
>> Bedenke, dass der Interrupt erst ausgeführt wird, nachdem der gerade
>> bearbeitete Befehl abgearbeitet wurde.
> Der Fehler ist aber konstant und fällt weg, wenn ich relativ von einem
> Break zum anderen messe. An den Zahlen ändert sich auch nichts, wenn ich
> den Breakpoint ans Ende der ISR setze.

In der ISR hast du immer die Unsicherheit, dass ein Befehl im 
übergeordneten Programm mal einen bis mehrere Takte länger dauert und du 
deshalb den Breakpoint in der Interrupt-Routine mal scheinbar früher 
oder später erreichst. Nur im Mittel über viele Durchläufe erhältst du 
dann die 8000000.
OP #3484554
Helmut S. schrieb:
> Nur im Mittel über viele Durchläufe erhältst du
> dann die 8000000.

Nach 40 Interrupts erreiche ich 319.999.960(PR1=31249) / 
320.010.200(PR1=31250) Zyklen:
319.999.960/40=7.999.999
320.010.200/40=8.000.255

mknoelke schrieb:
> Der Prescaler legt Deine kleinste Zeiteinheit fest die der Timer dann
> nur noch abzählt.
Daher kommen die 256 Zyklen stufen, nur den Offset von einem Zyklus 
verstehe ich nicht.
Gast #3484648
Max H. schrieb:
> Die 255 lassen vermuten, dass das
> irgendetwas mit dem 1:256 Prescaler zu tun hat.

Schau mal im Datenblatt unter welchen Bedingungen der Prescaler gelöscht 
wird. Möglicherweise beschreibst Du im Interrupt eines der kritischen 
Register.

Gruß Anja
Gast #3484672
Max H. schrieb:
> Gibt es einen Trick um
> genau auf die 0.5 Sekunden (8.000.000Zyklen) zu kommen?

Ja, du musst warten bis die 0,5s abgelaufen sind.

Dafür springst du kurz vor Ablauf in die Routine und wartest bis das 
Timer Flag triggert.
OP #3485532
Anja schrieb:
> Schau mal im Datenblatt unter welchen Bedingungen der Prescaler gelöscht
> wird.
Zitat "PIC24F Family Reference Manual, Sect. 14 Timers":
>The prescaler counter is cleared when any of the following occurs:
>• A write to the TMRx register
>• Clearing TON (TxCON<15>) to ‘0’
>• Any device Reset

Anja schrieb:
> Möglicherweise beschreibst Du im Interrupt eines der kritischen
> Register.
Meine ISR sieht so aus:
1
  .global __T1Interrupt
2
  __T1Interrupt:
3
  bclr IFS0,#T1IF ; clear the interrupt flag
4
  com.b LATB+1
5
  retfie

Jens Martin schrieb:
> Dafür springst du kurz vor Ablauf in die Routine und wartest bis das
> Timer Flag triggert.
Ich habe dabei nur das Problem, dass das Interrupt Flag nach 
8.000.255/7.999.999 Zyklen gesetzt wird.

Der MicroE Timer Calculator schlägt diese Einstellungen vor:
1
void InitTimer1(){
2
  T1CON = 0x8030;  //1:256 Prescaler
3
  T1IE_bit= 1;
4
  T1IF_bit = 0;
5
  IPC0 = IPC0 | 0x1000;
6
  PR1 = 31250; 
7
}
Wenn ich diese Einstellungen in mein ASM Programm einbaue erhalte ich 
aber 8.000.255 Zyklen zwischen den Interrupts.
OP #3485791
Helmut S. schrieb:
> In der ISR hast du immer die Unsicherheit, dass ein Befehl im
> übergeordneten Programm mal einen bis mehrere Takte länger dauert
Ich habe gerade gelesen, dass die Interrupt Latenzzeit bei Two-Cycle und 
Single-Cycle Instructions die gleiche ist.

Das Problem sollte man nur haben, wenn man den DISI Befehl benutzt, 
mache ich aber nicht.
OP #3485855
Anja schrieb:
> Nur im Simulator oder auch im real life?
Das kann ich dir nicht sagen. Ich kann die 0.5s nicht mit einer 
Auflösung von <15.938µs Messen.

Edit:
Wenn ich das PR1 Register aber auf 10 setze sind es sowohl im Sumulator 
als auch im real life 175.9375µs (2815 Zyklen 10*256+255=2815)
Gast #3485895
Max H. schrieb:
> A write to the TMRx register

Dann wird wohl das Löschen des Timer-Registers beim Erreichen des 
Endwertes als Schreibzugriff gewertet und 1 Taktzyklus geht dabei 
verloren.
(normalerweise wird durch PR1+1 geteilt).

Vielleicht hilft ja ein 6.5536 MHz Quarz (Prescaler 64 und PR1 = 0xFFFF)

Gruß Anja
OP #3485966
Anja schrieb:
> (normalerweise wird durch PR1+1 geteilt).
Das habe ich mittlerweile begriffen. Wenn man darüber nachdenkt ist das 
auch logisch.

Noch ein Test:
PS=1:8
PR1=1
Zeit:
-MPLAB SIM: 937.5ns (15 Zyklen)
-Real live: 996ns (vllt. auch 1µs: Kein high ein Oszi)

Über 22 Timer überlauf Zyklen messe ich 22µs und Simuliere 20.625µs

Dieses Mal passen die errechneten Werte mit den Gemessenen zusammen. 
Dann könnte das mit dem fehlenden Zyklus ein Fehler in der SIM-Software 
sein.
Gast #3486004
Der ultimative Test wäre einen 2. Timer als PWM ohne prescaler laufen zu 
lassen.
Die Frequenz ist dann entsprechend Prescaler höher.

Wenn beide Kanäle phasenstarr bleiben dann ist die Simulation falsch.
Wenn der eine Kanal "durchläuft" wird der Prescaler gelöscht.

Gruß Anja
OP #3486023
Anja schrieb:
> Der ultimative Test wäre einen 2. Timer als PWM ohne prescaler
> laufen zu
> lassen.
> Die Frequenz ist dann entsprechend Prescaler höher.
>
> Wenn beide Kanäle phasenstarr bleiben dann ist die Simulation falsch.
> Wenn der eine Kanal "durchläuft" wird der Prescaler gelöscht.
So weit bin ich noch nicht. Ich werde aber mit da PWM Modul im DB 
anschauen und versuchen es zu programmieren. Wenn ich es geschafft habe, 
melde ich mich...
OP #3486055
Gar nicht so komplizier das PWM Modul.
Ich habe das PWM/TMR2 Modul so eingestellt:
PR2=51199
PS=1:1

TMR1:
PR1=199
PS=1:256

Die Phase bleibt jetzt schon seit 3min. gleich. Also ist das mit dem 
fehlendem wirklich ein Fehler im Simulator. Damit ist mein Problem jetzt 
gelöst und ich habe gelernt, wie ich das PWM Modul verwende...

Vielen Dank für die Hilfe! :-)

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 12 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.