www.mikrocontroller.net

Forum: Compiler & IDEs Interrupt in mehreren .c files


Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ralf Schwarz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stichwort Pointer auf Funktionen:

  * http://www.tu-chemnitz.de/urz/kurse/unterlagen/C/k...

Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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:
*************
uint8_t isr_Action;

ISR( .... )
{
  if( isr_Action == 0 )
    mache_dieses;

  else
    mache_jenes;
}

File1:
******
extern uint8_t isr_Action;

void foo1()
{
  .... setze alles mögliche auf, zb den Timer
  // Die ISR soll jetzt die Aktion mache_dieses ausführen
  isr_Action = 0;

  ...
}


File2:
******
extern uint8_t isr_Action;

void foo2()
{
  .... setze alles mögliche auf, zb den Timer
  // Die ISR soll jetzt die Aktion mache_jenes ausführen
  isr_Action = 1;

  ...
}

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte mir das so etwa vorgestellt: (eine rein schematische 
Darstellung des Codes !)
Mainprogramm:
******
#iclude <Funktion1.h>
#iclude <Funktion2.h>

main()
{
.
.
   funk1();
.
.
   funk2();

}

Funktion1.c
********
volatile int trigger = 0;

isr(timer0_vect)
{
   trigger = 1;
}


void funk1()
{
   Timer0 initialisieren und starten (45ms)
   while (trigger = 0)
   {
      generiert ein spezielles signal
   }
}


Funktion2.c
********
volatile int trigger = 0;

isr(timer0_vect)
{
   trigger = 1;
}

void funk2()
{
   Timer0 initialisieren und starten (60ms)
   while (trigger = 0)
   {
      macht irgendetwas ganz anderes
   }
}

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.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.