PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wie Interrupt (Output Compare) "manuell" auslösen?



Gock
18.12.2008, 11:09
Hallo!
Ich möchte den OutputCompareMatch0 Interrupt an einer bestimmten Stelle im Programm auslösen, ohne dass dieser wirklich stattfindet.
Wie kann ich das machen?

Ich weiß, dass das OCF0 Flag "1" werden muss, aber wie?
Mit

TIFR |= (1<<OCF0);
könnte ich es laut Datenblatt löschen (clearen), aber mit

TIFR &= ~(1<<OCF0);
kann ich es leider nicht setzen.
Wenn das der falsche Weg ist, vielleicht kennt wer eine andere Lösung...?

Vielen Dank schonmal,
Gruß Gock

Besserwessi
18.12.2008, 17:08
Den Interrupt kann man nicht so einfach auslösen. Es gibt zwar ein funktion um die OCxx Ausgänge entsprechend zu verändern, aber der Interrupt wird dabei nicht ausgelöst. Eventuell könnte man den Timerwert so ändern das der Interrupt dann bald kommt, das geht aber natürlich nicht immer. Das einzige was mir da sonst einfällt wäre den Interruptcode 2 mal zu haben, einmal als ISR und einmal als Unterprogramm (ggf. mit SEI / CLI).

Edit: man könnte eventuell auch die selbe ISR für sowohl den Compare als auch einen externen Interrupt nutzen und dann den externen Interrupt künstlich auslösen.

askazo
18.12.2008, 18:05
Warum so kompliziert?
Schreibe den Inhalt des Interrupts in eine Funktion.
Diese Funktion kannst Du dann sowohl aus dem Interrupt aufrufen als auch von jeder beliebigen anderen Stelle Deines Programms. Du solltest allerdings zu Beginn der Funktion den Interrupt deaktivieren und erst beim verlassen der Funktion wieder aktivieren, sonst kann es passieren, dass während des manuellen Aufrufs der Funktion der Interrupt dieselbe Funktion nochmal aufruft. Je nachdem kann das ordentlichen Kuddelmuddel geben....

Gruß,
askazo

Besserwessi
18.12.2008, 19:58
In der ISR sollte man mit Funktionen sparsam umgehen, denn die brauchen wieder ein paar extra Register. Das wider freigehen des Interrupts innerhalb der ISR ist auch nicht ideal, denn das kann auch zusätzlichen Stack verbrauchen durch geschachtelte ISRs.

wkrug
18.12.2008, 22:16
Ich möchte den OutputCompareMatch0 Interrupt an einer bestimmten Stelle im Programm auslösen, ohne dass dieser wirklich stattfindet.
Was soll der Auslöser für diese Aktion sein ?
Ein anderer Interrupt ? - Frei aus dem Programm heraus ? - Eine Portabfrage ?
Mir fallen da mehrere Möglichkeiten ein, je nach Anwendungsfall.
Schilder mal in etwa was Du vorhast, dann kann man auf das Problem konkreter eingehen.

thewulf00
19.12.2008, 09:13
Obwohl Besserwessi dagegen ist, finde auch ich, dass eine gemeinsame Funktion für ISR und manuelles Auslösen die beste Variante darstellt.

Gock
19.12.2008, 09:21
Hallo allerseits!
@Besserwessi
So hatte ich es auch verstanden, hatte gehofft, es gibt noch einen Weg. Das "FOC" Bit habe ich auch schon gesehen und kurz gehofft, aber nur kurz...
Zur Zeit habe ich den Code tatsächlich zweimal im Programm, weil ich aus der ISR keine Funktion aufrufen möchte.
Der Umweg über einen anderen IRQ (zB ExtIRQ) ist eine Idee, die ich mir mal merke. Allerdings habe ich in diesem Fall diese Möglichkeit nicht.

@askazo, thewulf00
Wie gesagt, ich will aus der ISR keine Funktion aufrufen. Dadurch spare ich Speicher und Laufzeit. Dann lieber 2 mal denselbsen Code hinschreiben, was in meinem Fall geringerer Resourcenverbrauch zur Folge hätte.
Außerdem wäre es so schön einfach, wenn man den IRQ mal nebenbei auslösen könnte und es hat mich auch einfach interessiert.

@wkrug
Manche IRQs kann man auslösen, indem man das entsprechende Flag an einer beliebihgen Stelle im Code auf "1" setzt. Aber beim OCF0 geht das nicht, keine Ahnung, warum.
Man könte sich dadurch eine "init"-Funktion sparen, zB in Fällen, in denen die ISR ohnehin jedesmal dieselbe Init benötigt.
Danke,
Gruß Gock

thewulf00
19.12.2008, 09:44
@askazo, thewulf00
Wie gesagt, ich will aus der ISR keine Funktion aufrufen. Dadurch spare ich Speicher und Laufzeit. Dann lieber 2 mal denselbsen Code hinschreiben, was in meinem Fall geringerer Resourcenverbrauch zur Folge hätte.
Außerdem wäre es so schön einfach, wenn man den IRQ mal nebenbei auslösen könnte und es hat mich auch einfach interessiert.

Dann schreib das Wörtchen INLINE in die Funktionsdeklaration. Dadurch weiß der Compiler, dass es keine Funktion sein soll, sondern nur gemeinsam genutzter Code, d.h. er fügt es selbst an die aufzurufenden Stellen ein, OHNE eine Funktion aufzurufen.

Besserwessi
19.12.2008, 10:51
Der Hinweis mit dem Inline ist gut, auch wenn der code dann trotzden 2 mal im ergebins auftaucht. Immerhin vermiedet man so das man Änderungen an 2 Stellen machen muß und dann versehentlich doch verschiedenen Versionen hat.

Ceos
19.12.2008, 11:20
soweit ich weis gibt es einen force output compare match flag schau mal ins datenblatt

oberallgeier
19.12.2008, 12:41
... schreib das Wörtchen INLINE ... nur gemeinsam genutzter Code ... OHNE eine Funktion aufzurufen.DAS ist wichtig! Ich verstehe das jetzt so, dass durch dieses Inline"makro" NUR der Code eingesetzt wird und keine zusätzlichen Registerrettungsmassnahmen oder sonstiger Overhead erfolgen.

Irgendwie hatte ich diese Stelle (https://www.roboternetz.de/wissen/index.php/C-Tutorial#Inlining) bisher nicht (richtig) verstanden.

Jedenfalls danke für so einen Tip.

Gock
19.12.2008, 15:16
Ja das klingt doch nach einer guten Idee mit dem Inlining. Dann bleibt der Code wenigstens an beiden Stellen gleich.

Der Force Output Compare ("FOC" siehe oben) löst leider keinen Interrupt aus...
Gruß