Forum: Mikrocontroller und Digitale Elektronik Taktgenaue Interrupt - Abarbeitung und das ohne Jitter ?


von Bernhard S. (bernhard)


Lesenswert?

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

von Olaf (Gast)


Lesenswert?

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

von Bernhard S. (bernhard)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von leo9 (Gast)


Lesenswert?

@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

von Christoph Söllner (Gast)


Lesenswert?

> 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.

von Bernhard S. (bernhard)


Lesenswert?

@ 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
Noch kein Account? Hier anmelden.