Hallo, ich habe folgendes Problem: Ich möchte in verschiedenen .h und .c files verschiedene Funktionen erstellen. (Impulsvariante 1, Impulsvariante 2). In beiden Funktionen soll der selbe Timer mit seinem Interrupt verwendet werden. Im Hauptprogramm werden die Funktionen aufgerufen und auch immer gewartet bis die Funktionen vollständig abgelaufen sind. Wie kann ich nun in den beiden .c files auf den Interrupt ISR(TIMER0_COMPA_vect) zugreifen ohne ihn mehrfach zu definieren? Gruß Norton
Norbert S. wrote: > Wie kann ich nun in den beiden .c files auf den Interrupt > ISR(TIMER0_COMPA_vect) zugreifen ohne ihn mehrfach zu definieren? Ich verstehe dein Fragestellung nicht ganz. Was soll 'auf den Interrupt zugreifen' bedeuten? Auf einen Interrupt oder auf eine ISR greift man überhaupt nicht zu. Eine ISR wird automatisch aufgerufen, wenn das entsprechende Ereignis eingetreten ist. Die ruft man nicht selber auf, noch kann es mehr als eine ISR für eine bestimmtes Ereignis im Programm geben.
Stichwort Pointer auf Funktionen: * http://www.tu-chemnitz.de/urz/kurse/unterlagen/C/kap2/fktptr.htm
Ich hab mich falsch ausgedrückt, ich möchte bei zwei Funktionen in verschiedene .c files den Timer0 verwenden. Wobei bei beiden im Ereignis des Timers etwas ausgelöst wird. > noch kann es mehr > als eine ISR für eine bestimmtes Ereignis im Programm geben. Das ist mein problem welches ich irgendwie lösen möchte (muss).
Allerdings ist das Aufrufen von Funktionen aus ISRs heraus sehr teuer. Ausnahme sind Funktionen, die inline expandiert werden, was beim Aufruf über Pointer aber grundsätzlich nicht geht.
@ Norbert S. Durchlaufender Timer mit eigenen Variablen (global, volatile). Die Funktionen aus dem Hauptprogramm greifen lesend auf die Timervariablen zu. Beispiel Uhr: Timer setzt z.B. Millisekunden, Sekunden, ... Die Funktionen lesen die Werte und entscheiden anhand von eigenen Triggerwerten, ob sie was erledigen müssen.
> Allerdings ist das Aufrufen von Funktionen aus ISRs heraus sehr teuer.
Naja, das hängt ein bisschen davon ab, wie oft der entsprechende
Interrupt ausgelöst wird. Wenns ein Timerinterrupt im 100msec-Takt ist,
dann darf auch die ISR etwas Zeit verbraten, wenns ein RX-Interrupt
einer mit mehr als 115200 Baud betriebenen seriellen Schnittstelle ist,
dann sieht die Lage schon anders aus.
Norbert S. wrote: >> noch kann es mehr >> als eine ISR für eine bestimmtes Ereignis im Programm geben. > > Das ist mein problem welches ich irgendwie lösen möchte (muss). Du benutzt eine globale Variable, die der einzigen ISR Funktion mitteilt was sie zu tun hat. File_mit_ISR: *************
1 | uint8_t isr_Action; |
2 | |
3 | ISR( .... ) |
4 | {
|
5 | if( isr_Action == 0 ) |
6 | mache_dieses; |
7 | |
8 | else
|
9 | mache_jenes; |
10 | }
|
File1: ******
1 | extern uint8_t isr_Action; |
2 | |
3 | void foo1() |
4 | {
|
5 | .... setze alles mögliche auf, zb den Timer |
6 | // Die ISR soll jetzt die Aktion mache_dieses ausführen
|
7 | isr_Action = 0; |
8 | |
9 | ...
|
10 | }
|
File2: ******
1 | extern uint8_t isr_Action; |
2 | |
3 | void foo2() |
4 | {
|
5 | .... setze alles mögliche auf, zb den Timer |
6 | // Die ISR soll jetzt die Aktion mache_jenes ausführen
|
7 | isr_Action = 1; |
8 | |
9 | ...
|
10 | }
|
>> Allerdings ist das Aufrufen von Funktionen aus ISRs heraus sehr teuer. > > Naja, das hängt ein bisschen davon ab, wie oft der entsprechende > Interrupt ausgelöst wird. Und eben davon ab, wie lange die Interrupts gesperrt bleiben dürfen. Außerdem braucht es ja nicht nur zusätzliche Laufzeit, sondern auch Speicher (und zwar sowohl Flash, als auch RAM).
Ich hatte mir das so etwa vorgestellt: (eine rein schematische Darstellung des Codes !)
1 | Mainprogramm:
|
2 | ******
|
3 | #iclude <Funktion1.h>
|
4 | #iclude <Funktion2.h>
|
5 | |
6 | main() |
7 | {
|
8 | .
|
9 | .
|
10 | funk1(); |
11 | .
|
12 | .
|
13 | funk2(); |
14 | |
15 | }
|
16 | |
17 | Funktion1.c |
18 | ********
|
19 | volatile int trigger = 0; |
20 | |
21 | isr(timer0_vect) |
22 | {
|
23 | trigger = 1; |
24 | }
|
25 | |
26 | |
27 | void funk1() |
28 | {
|
29 | Timer0 initialisieren und starten (45ms) |
30 | while (trigger = 0) |
31 | {
|
32 | generiert ein spezielles signal |
33 | }
|
34 | }
|
35 | |
36 | |
37 | Funktion2.c |
38 | ********
|
39 | volatile int trigger = 0; |
40 | |
41 | isr(timer0_vect) |
42 | {
|
43 | trigger = 1; |
44 | }
|
45 | |
46 | void funk2() |
47 | {
|
48 | Timer0 initialisieren und starten (60ms) |
49 | while (trigger = 0) |
50 | {
|
51 | macht irgendetwas ganz anderes |
52 | }
|
53 | }
|
Mein Ziel währe es, dass im Hauptprogramm nur die Funktionen aufgerufen werden können ohne viele status und sonstige Variablen für diese Funktionen zu sehen. Es soll der Programmablauf im Hauptprogramm so einfach wie möglich nachempfunden werden können. Weiter sollen diese Funktionen ohne Probleme für weitere Projekte weiterverwendet werden können.
Kann man in dem Fall so machen. funk1 und funk2 benutzen den Timer in dem Beispiel ja exklusiv und behindern sich nicht gegenseitig. Ist keine besonders schöne Lösung, naja. Mein Vorschlag mit dem durchlaufenden Timer würde den Timer einmal ausserhalb von funk1 und funk2 so aufsetzen, dass er z.B. mit dem grössten gemeinsamen Teiler der zeitscheiben läuft (45ms, 60ms => 15ms Timer) und dass er bei jedem Aufruf einen Tick hochzählt. Dann fragen funk1 und funk2 vor dem while den aktuellen Tickstand ab und führen die while Schleife so lange aus, bis der Startwert + Zeitspanne (in Ticks) erreicht ist. Wenn der Timer mehr Rechenzeit verbraten darf, kann man den auch mit 1 ms Auflösung laufen lassen. dann sieht der Code hübscher aus. Oder man benutzt für Startwert + Zeitspanne Makros, die das Teilen in Ticks verbergen...
Welchen Teil des Satzes "Für ein bestimmtes Ereignis kann es in einem C Programm nur einen einzigen ISR Handler geben." verstehst du nicht?
Karl heinz Buchegger wrote: > Welchen Teil des Satzes > "Für ein bestimmtes Ereignis kann es in einem C Programm > nur einen einzigen ISR Handler geben." > verstehst du nicht? Ich weiss, daß das nicht funktioniert, ich würde gerne eine elegante Alternative dafür haben. (Ich stelle mir das ja nur so vor)
Norbert S. wrote: > Karl heinz Buchegger wrote: >> Welchen Teil des Satzes >> "Für ein bestimmtes Ereignis kann es in einem C Programm >> nur einen einzigen ISR Handler geben." >> verstehst du nicht? > > Ich weiss, daß das nicht funktioniert, ich würde gerne eine elegante > Alternative dafür haben. (Ich stelle mir das ja nur so vor) Entweder, wie oben gezeigt, mit einer Action Variablen arbeiten die der ISR sagen was zu tun ist, oder in der ISR über einen Funktionspointer eine benutzerdefinierte Funktion aufrufen lassen. Andere Möglichkeiten (*) gibt es nicht (*) Es gibt schon noch eine Möglichkeit in der klassischen Hauptschleifenprogrammierung: Die ISR setzt eine globale Variable zb auf 1 und in der Hauptschleife in main() wird entschieden was dann zu tun ist. Das kann man aber mit viel gutem Willen als Variante der Methode "globale Variable bestimmt in der ISR was zu tun ist" auffassen. Mit dem Unterschied, dass Rechenzeit von der ISR abgezogen und in die Hauptschleife verlagert wird. Es hilft alles nichts: So einen AVR muss man anders programmieren als einen PC. Und aus der Tatsache, dass sich ISR nicht zur Laufzeit installieren lassen (eine direkte Konsequenz aus der Harvard- Architektur), folgt dann so Einiges. Ein Funktionspointer ist dann noch die Methodik mit der man am nächsten an installierbare ISR Routinen herankommt.
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.