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
Wie misst du diese Zyklen? In dem du misst, wenn die erste Zeile in der Interrupt-Routine ausgeführt wird? Bedenke, dass der Interrupt erst ausgeführt wird, nachdem der gerade bearbeitete Befehl abgearbeitet wurde.
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.
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.
> 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.
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.
:
Bearbeitet durch User
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
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.
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.
:
Bearbeitet durch User
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.
:
Bearbeitet durch User
Max H. schrieb: > Wenn ich diese Einstellungen in mein ASM Programm einbaue erhalte ich > aber 8.000.255 Zyklen zwischen den Interrupts. Nur im Simulator oder auch im real life? Gruß Anja
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)
:
Bearbeitet durch User
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
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.
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
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...
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! :-)
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.