Forum: Compiler & IDEs Interrupt in mehreren .c files


von Norbert S. (norton)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Ralf Schwarz (Gast)


Lesenswert?


von Norbert S. (norton)


Lesenswert?

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

von Rolf Magnus (Gast)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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
}

von Rolf Magnus (Gast)


Lesenswert?

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

von Norbert S. (norton)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

Welchen Teil des Satzes
"Für ein bestimmtes Ereignis kann es in einem C Programm
nur einen einzigen ISR Handler geben."
verstehst du nicht?

von Norbert S. (norton)


Lesenswert?

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)

von Karl H. (kbuchegg)


Lesenswert?

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