Hallo zusammen !
ich hab ein kleines Problem mit meiner Interrupt Routine. Ich benutze
einen HCS12 Mikrocontroller. Habe die Busfrequenz über PLL auf 24 MHz
eingestellt. Nun hab ich eine Interrupt Routine programmiert, die mir in
bei fallender Flanke eines Eingangssignals ein paar Berechnungen macht
und einen Wert in ein Output Compare Timer Register schreibt für eine
Impulsausgabe.
Habe mit COdewarrior die Buszyklen gemessen, die ich für die ISR
benötige, woraus sich ja die minimale Zeit zwischen zwei fallenden
Flanken ergibt, in der die ISR noch komplett ausgeführt wird. Bei den
Buszyklen komme ich im worst case auf 1054 cycles. Bei einem Bustakt von
24 MHz entsrpicht dies einer Zeit von 43,92µs. Das hieße, dass mein
Eingangssignal minimal sagen wir mal alle 44 µs eine fallende Flanke
liefern darf, damit die ISR noch korrekt funktioniert.
Anhand von Tests mit dem Oszi hab ich aber festgestellt, dass die
minimale Zeit, bei der ich noch korrekte Impulsausgabe bekomme, bei etwa
122 µs liegt.
Kann mir jemand sagen ob ich in meinen Überlegungen komplett falsch
liege oder was da Sache sein könnte ?? Bin relativ neu in Sachen µC.
Hab mal die FUnktion Cap1_OnCapture die von der ISR aufgerufen wird
angehängt.
Grüße
Stefan
Um dir mal klar zu werden welchen Takt du hast, aktiviere mal den
E-Clock (müsste am PORTE sein) und messe nach. Das ist dann der Busclock
und der ist Osc/2. Gleiches gilt bei der Nutzung der PLL. Freescale hat
da eine ganz verwirrende Beschreibung von Clock und Takt.
Eventuell sind auch einige Register nicht korrekt configuriert
(Vorteiler abgeleitet aus dem Busclock).
Ansonsten unbedingt den Spurious Interrupt mit einer ISR behandeln.
Eventuel ein Portpin toggeln damit du weisst wie oft du da reinkommst.
JL
Wie jl schon sagte: BusClock = PLLCLK/2
Wenn also deine PLL mit 24MHz läuft, ist deine BusClock =12MHz.
Eventuell musst du auch die Laufzeiten in der Hauptschleife
berücksichtigen, in denen z.B. die Interrupts kurz gesperrt sind (falls
das bei dir zutrifft). Vielleicht sind bereits andere Ints am Laufen
(z.B. Serielle SS), wenn das Signal reinkommt. Dann musst du noch
sicherstellen, dass dir der BDM-Debugger nicht reinspuckt, falls der
angeschlossen ist.
Erstmal Danke für die Antworten !
Werd mal versuchen die Clock zu messen. Den Einstellungen nach müsste
der PLL bei 48 MHz liegen und der Bus damit bei 24 MHz.
Insgesamt hab ich 4 Interrupts wobei ich der längsten ( eigentlich das
Hauptprogramm) die höchste Prio gegeben hab.
Das mit der BDM Schnittstellt hab ich jetzt gar nich beachtet, werd ich
auch mal untersuchen.
Hab inzwischen auch festgestellt, dass ich bei einer bestimmten
Eingangsfrequenz des Capture Signals Aussetzer bei der Impulsausgabe
hab. Da scheinen sich die ISR wohl irgendwie in die Quere zu kommen.
Bin dann mal wech am Oszi...
Ok erstmal nochmal thx für die Antworten.
Habs inzwischen ganz gut hinbekommen. Allerdings habe ich noch eine
Frage.
Ich kann über das HPRIO Register ja nur einem Interrupt höchste
Priorität zuweisen und das wirkt dann auch nur, wenn 2 Interrupts
gleichzeitig auftreten. Nun die Frage : Ist es möglich festzulegen,
dass 2 Interruptroutinen jede andere Routine unterbrechen können ?
Ich würde gerne meine Timer Output COmpare ISRs so konfigurieren, dass
sie die Input Capture Routine unterbrechen können.
Hoffe ihr könnt mir weiterhelfen !
Gruß
Stefan
Ein weiteren Punkt hab ich noch.
ab ner bestimmten Eingangsfrequenz des Signals am Input Capture (
~8,2kHz) fangen meine Output COmpare ISR an sich wild zu verschieben und
die capture ISR setzt ab und zu aus ( wird nicht mehr durchlaufen). Rein
zeitlich könnten die ISR aber durchaus noch alle abgehandelt werden
innerhalb von 2 fallenden Flanken....
Bei 9kHz wird dann gar keine ISR mehr ausgeführt ?!
>Ich kann über das HPRIO Register ja nur einem Interrupt höchste>Priorität zuweisen und das wirkt dann auch nur, wenn 2 Interrupts>gleichzeitig auftreten. Nun die Frage : Ist es möglich festzulegen,>dass 2 Interruptroutinen jede andere Routine unterbrechen können ?
Beim HCS12 sind nach Eintritt in eine ISR weitere Ints gesperrt (I-FLAG)
(von den nicht maskierbaren und X-maskierten abgesehen)
Wenn du in der ISR das I-Flag löscht, können ALLE freigeschalteten
Interruptquellen die laufende ISR unterbrechen. Beim Nachfolger S12X
wurde der Interrupt-Block umgebaut, kann sein dass es dort nativ so
funktioniert, wie du es vorhast. Beim S12 musst du dir irgendwelche
SW-Tricks einfallen lassen.
Dein externes Triggersignal (so nenne ich es mal), wie fängst du das
ein? Über normalen Port_x-Int oder über InputCapture-Int?
Warum das ab 8,2kHz nicht mehr funktioniert, kann nur dein Quelltext
verraten.
PS
oben schreibst du:
>Insgesamt hab ich 4 Interrupts wobei ich der längsten ( eigentlich das>Hauptprogramm) die höchste Prio gegeben hab.
Also ich weis nicht. Ich glaube, du bist ein recht skrupelloser
Programmierer. Mach mal ein paar worst-case Überlegungen bez. Laufzeiten
und Aufruffrequenzen von ISRs.
Hehe skrupellos kann gut sein :P und danke für die schnelle Antwort.
Also ich hab das mit dem I-Bit im CCR Register jetzt eingebaut und
scheint zu funktionieren. Die Timing Betrachtungen zu den Interrupt
Laufzeiten hab ich inzwischen auch gemacht. Dabei hab ich eben
festgestellt, dass die Interrupts ab ner bestimmten Eingangsfrequenz des
Eingangssignals ( welches übrigens über Input Capture Timer eingefangen
wird) erst beginnen ab und zu auszusetzen oder sich zeitlich zu
verschieben, um dann bei ner höheren Frequenz gar nicht mehr ausgelöst
zu werden ( getestet mit Oszi und Ausgang am Anfang der ISR setzen und
am Ende rücksetzen).
Dabei hab ich auch gesehen, dass die ISR sich rein zeitlich gesehen
nicht in die Quere kommen, heisst also keine Überlagerung von ISR oder
so. Und irgendwie erscheint mir das komisch, wenn die auf einmal
aufhören zu funktionieren :) zumindest die Input capture ISR sollte doch
eignetlich immer ausgelöst werden, aber auch die setzt irgendwann aus
und wird dann gar nicht mehr aktiviert.
Mysteriöse Geschichte das :P
Vielleicht noch eine kleine Zusatzfrage, die mich interessieren würde.
WIe genau ist das Input Capture ? weil ich hab bei meinem Ausgangsimpuls
der ja auf dem erfassten Zeitwert basiert irgendwie 15µs Schwankungen.
Habe bereits versucht, einfach nur einen konkreten Wert auf den
erfassten Zeitwert zu addieren und da dann nen Impuls per output compare
interrupt auszugeben, aber auch da schankt der Impulszeitpunkt um 15µs.
hab grad mal nen neues Projekt erstellt in Codewarrior nur mit ner Input
Capture Routine. 8 Mhz Bustakt und 64 Prescaler.
In der Routine wird nurn Port an und wieder aus geschaltet. Und sogar
ohne sonstigen Code funktioniert der Inupt Capture nur bis zu einer
bestimmen Frequenz ~8,5 kHz.
Prozessor ist : MC9S12C64
Den Code kann ich erst Montag wieder posten, da ich über WE weg bin.
Im Prinzip isses aber nur mit codewarrior input capture bean erstellt
und in der ISR nen port an und aus schalten. Input capture channel is
TC0. CPU is eingestellt auf externe 8 MHz Oszillator Clock und über PLL
highspeed mode auf 8 MHz Bustakt gebracht.
Naja wie gesagt, kann Montag dann den Code mal posten.
Bis dahin schönes WE !
Hi also hab den Fehler gefunden :P Schuld scheint die Hardware zu sein.
Irgendwie wird der eingangsimpuls nicht rechtzeitig auf Vcc gezogen um
dann eine fallende Flanke zu detektieren. Bin mir noch nicht ganz sicher
woran es genau liegt, da der 4N25 Opto eigentlich schnell genug sein
müsste aber ok, wenigstens bin ich jetzt weiter.
Danke für die Unterstützung !
Gruß