Geschätztes Forum Ein großes Problem beschäftigt mich seit Tagen. Ein Timer-Interrupt soll taktgenau abgearbeitet werden. (Generierung eines Video-Signals) Problem: Arbeitet gerade der µC in seinem Hauptprogramm einen Befehl ab, der mehrere Takte benötigt (zb. 4 Takte für "RET"), dann kann zwar ein Interrupt ausgelöst werden, aber dieser Interrupt wird erst einige Takte später abgearbeitet. Es entsteht ein "Jitter" (zittern) Was haltet Ihr von dieser Lösung. Ein Timer-0 löst einige Takte vor dem eigentlichen Haupt-Timer-1 aus und versetzt den µC in einen SLEEP-IDE-Modus. Durch "SEI" wird ermöglicht, dass Timer-1 auslösen und takttreu "abgearbeitet" werden kann. Denn der µC befindet sich ja in einem definierten SLEEP-Modus, und nicht bei irgend einem Befehl der 1...4 Takte dauert. Nachteil: Man benötigt zwei Timer. Gibt es noch andere Möglichkeiten? Danke Bernhard
Was hälst Du von folgender Idee: Timer-Interrupt normal beibehalten, dann im Interrupt zuerst den Zählerstand (A) holen. Da sich dieser nur in einem bestimmten Zahlenbereich bewegen kann (Latenz durch z.B. RET verzögert), wartet man dann n-A Takte (n größter anzunehmender Wert), bevor man mit dem Interrupt fortfährt. Da sich das Delay-Loop nicht eignet (zu grob), würde ich auf handgestrickte "nop"-Folgen setzen Sollte eigentlich machbar sein
Hallo Olaf, die "Zählerstand" Methode ist interessant, gefällt mir, setzt natürlich voraus, dass der Vorteiler des Timers auf 1 gesetzt ist. Einfach den aktuellen Zählerstand auslesen und bei Bedarf durch NOP ausgleichen. Schöne Idee! Bernhard
Für Jitterfreiheit eignen sich auch die PWM-Ausgänge sehr gut. Sie werden per Hardware völlig jitterfrei beim Compare-Match gesetzt. Der Interrupt muß also nur die neue Comparezeit eintragen und ob der Pin toggeln, 1 oder 0 gesetzt werden soll. Es gibt aber auch ne Applikation Note in Assembler (auf Atmel oder AVRFreaks), wo die Einsprungszeit ausgeglichen wird. Peter
@Bernhard: das gleiche Problem hatte ich auch beim Videogenerieren und beim Video-Daten Auslesen. Ich habe das Problem dadurch gelöst dass ich einen "Vorinterrupt" auslöse, welcher erst sei macht und dann 20 mal nopt. Funktioniert perfekt und kommt deiner Sleep Variante sehr ähnlich. (und der Nachteil von zwei Timern besteht weiterhin, eventuell könnte man den Vorinterrupt mit Compare auslösen und den Echten mit Overflow, dan brauchts nur einen Timer .-) Grüsse leo9
> Funktioniert perfekt...
Das tät ich gern mal mit nem LeCroy anschauen, habe da so meine
Zweifel, ob das wirklich genau geht, und habe Erfahrung mit
Phasenanschnitts-Dimmern, dafür war es nicht genau genug; Lampen
flimmerten (Dreh die Timebase mal in den ns-Bereich). Übel wird es
erst, wenn Du noch andere Interrupts bekommst, z.B vom UART...
Du mußt ja einen Timer immer erstmalig starten, wenn der jetzt versetzt
anläuft, errechne mir mal die Anzahl der nötigen NOPs.
Außerdem kann der yC solange nichts anderes machen. Nimm einen 16 Bit
PWM-Ausgang und programmiere ihn auf die entsprechenden
Compare-Matches->Pin-Toggle. Frequenz kann natürlich im Hauptprogramm
angepaßt werden... Ist denke ich die einzige sinnvolle Lösung.
@ alle ich danke Euch für die zahlreichen Antworten und Ideen :) Musste allerdings feststellen, dass es auf den jeweiligen Anwendungsfall ankommt, welches verfahren man nutzen kann. In meinem konkreten Anwendungsfall habe ich mich für die "Zählerstand-Methode" entschieden. Denn nicht nur der V/H Synchron-Impuls muss taktgenau generiert werden, sondern auch die einzelnen Bilddaten einer Zeile (u.a. vordere Schwarzschulter, hintere Schwarzschulter, Trabanten usw.) Sollte auch nur ein einzelner Takt fehlen (das sind nur 0,0625µs bei 16Mhz), dann flimmert das Bild oder der Bildinhalt wird durch "Nadeln" geschmückt. Für den eigentlichen Taktausgleich habe ich den Befehl IJMP verendet. Hoch lebe der Erfinder dieses Befehls. Denn mit "cpi" ginge es auch, wäre nur umständlicher. Ich lege mal einen Auszug dieser Taktausgleichs-Routine mit bei. Bernhard ; ###################################################################### ; TAKT-Synchronisation TIMER2 auslesen in temp1, TCNT2 ; ###################################################################### ; TIMER0 Startwert ldi temp, TIMERWERT0 out TCNT0,temp ; TAKT-Synchronisation Fehlerprüfung cpi temp1,(30+1) ; Vergleich? brlo TAKT_SYNCHRONISATION_START ; kleiner ==> SPRUNG ; TAKT-Synchronisation TIMER2 auf WERT setzen LDI temp,11 out TCNT2,temp clr TEMP1 TAKT_SYNCHRONISATION_START: ; TAKT-SYNCHRONISATION-BERECHNEN ldi ZL,low(TAKT_SYNCHRONISATION) ldi ZH,HIGH(TAKT_SYNCHRONISATION) add ZL,temp1 adc ZH,NULL IJMP ; SPRUNG (Adresse in Z) TAKT_SYNCHRONISATION: nop ;0 nop nop nop nop nop ;5 ... ...
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.