Forum: Mikrocontroller und Digitale Elektronik Mehrere gleichnamige Interrups AtMega328P


von Dhaza (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

ich benutze einen AtMega328P in einem LED RGBW Projekt. Ich programmiere 
in C und nutze das AtmelStudio.

Mittels Funktionszeigern und einem kleinen Schalter auf meiner PCB 
möchte ich zwischen zwei unterschiedlichen Modi der PCB umschalten 
können.

Den ersten Modus habe ich programmiert (funk0) und alles funktioniert 
zufriedenstellend:

Über 4 Micro-Taster auf dem Board können die 4 Farben unabhängig 
voneinander angesteuert werden. Gemacht habe ich das über einen Timer 
Overflow-Interrupt an Zähler 0, wobei dann in der Interrupt-Routine die 
4 Kanäle geregelt werden.

Um Modus 2 zum Laufen zu bringen stehe ich aber  vor einem kleinen 
Problem. Auch hier möchte ich den Timer0 Overflow interrupt nutzen, 
allerdings auf eine andere Art. Das würde aber bedeuten, dass ich zwei:

ISR(TIMER0_OVF_vect){ ... }

habe.

Im Moment steht die ISR vor der Main(){...} und außerhalb meiner zwei 
Funktionen, die ich über Funktionszeiger auswählen kann (zur Erklärung: 
funk1 ist noch nicht programmiert, einfach leer, das soll sich jetzt 
aber ändern):

(Bild anhängend)

Dass es so nicht geht, wenn ich unterschiedliche ISRs für die beiden 
Funktionen brauche, das habe ich verstanden... aber wie macht man es?

Kann ich die ISR(TIMER0_OVF_vect){ ... } in funk0 und funk1 jeweils 
unterschiedlich anlegen, auch wenn sie dann erst beim Funktionsaufruf 
angelegt werden?

von Cyblord -. (cyblord)


Lesenswert?

Ich hoffe es gibt in der Hölle eine ganz spezielle Ecke für Leute die 
Quellcode als Bild posten.

von Einer K. (Gast)


Lesenswert?

Dhaza schrieb:
> Mittels Funktionszeigern und einem kleinen Schalter auf meiner PCB
> möchte ich zwischen zwei unterschiedlichen Modi der PCB umschalten
> können.
Was hindert dich?

Dhaza schrieb:
> Kann ich die ISR(TIMER0_OVF_vect){ ... } in funk0 und funk1 jeweils
> unterschiedlich anlegen, auch wenn sie dann erst beim Funktionsaufruf
> angelegt werden?
Das ist wirr!

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Dhaza schrieb:
> Das würde aber bedeuten, dass ich zwei:
>
> ISR(TIMER0_OVF_vect){ ... }
>
> habe.

Du kannst ein Flag setzen, das in der ISR abgefragt wird und dann 
verzweigt.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Cyblord -. schrieb:
> Quellcode als Bild
Und dann gleich noch als JPEG.

Dhaza schrieb:
> Mittels Funktionszeigern und einem kleinen Schalter auf meiner PCB
> möchte ich zwischen zwei unterschiedlichen Modi der PCB umschalten können.
Der Ansatz mit solchen Funktionspointern ist scheinbar elegant und 
zumindest kompliziert zu lesen.

> Um Modus 2 zum Laufen zu bringen stehe ich aber  vor einem kleinen
> Problem. Auch hier möchte ich den Timer0 Overflow interrupt nutzen,
> allerdings auf eine andere Art.
Du wirst mit dieser "Komplettumschaltung des Controllers je nach Modus" 
noch auf beliebig andere Probleme stoßen.

> den Timer0 Overflow interrupt nutzen, allerdings auf eine andere Art.
In einem Interrupt sollte im Grunde so wenig wie möglich gemacht werden. 
Ich setze in Timerinterrupts meist nur Flags, die dann im 
Zustandsautomaten der Hauptschleife abgearbeitet werden.

> aber wie macht man es?
In der Praxis schaltet man nicht den ganzen Controller samt 
Funktionsadressen um, sondern man arbeitet mit Zustandsautomaten. Dort 
wird dann einfach das Eingangsbit abgefragt und dann explizit die 
gewünschte "Funktion" ausgeführt. Und diese "Funktion" ist dann nur ein 
Zweig einer FSM (die zyklisch und schnellstmöglich durchlaufen wird), 
nicht eine "All Inclusive"-Routine.

Dhaza schrieb:
> Das würde aber bedeuten, dass ich zwei:
> ISR(TIMER0_OVF_vect){ ... }
> habe.
Du könntest in dieser einen ISR wieder über Funktionspointer 
unterschiedliche ISR-Unter-Unterroutinen aufrufen:
1
ISR(TIMER0_OVF_vect){
2
   ISR_Funktion[PINC&1]();
3
}

: Bearbeitet durch Moderator
von Dhaza (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Was hindert dich?

Dass ich je Modus eine andere ISR(TIMER0_OVF_vect) brauche und ich nicht 
weiß wie ich das formal mache

Arduino Fanboy D. schrieb:
> Das ist wirr!

Ja, tut mir leid.

von Cyblord -. (cyblord)


Lesenswert?

Mir ist immer noch die klar, warum nicht die offensichtliche Lösung 
gewählt wurde: In der ISR wird eine Funktion über einen Funktionszeiger 
aufgerufen.
Da braucht es keine Unterscheidungen an dieser Stelle.
Diesen Zeiger kann man dann (vorher) dynamisch auf die gerade gewünschte 
Funktion zeigen lassen.
Das erfordert auch keinen Unsinn mit der ISR selber. Es kommt halt ein 
Funktionsaufruf hinzu.

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Dhaza schrieb:
> Dass ich je Modus eine andere ISR(TIMER0_OVF_vect) brauche und ich nicht
> weiß wie ich das formal mache

Es gibt keine zwei ISR(TIMER0_OVF_vect) auf AVR.
Denn diese liegt unveränderbar im Flash.
Kann nicht ausgetauscht werden.


Du kennst doch schon FunctionPointer ...
Nutze sie!

von Oliver S. (oliverso)


Lesenswert?

Dhaza schrieb:
> Dass ich je Modus eine andere ISR(TIMER0_OVF_vect) brauche und ich nicht
> weiß wie ich das formal mache

Highlander: Es kann nur einen geben. Ist mit ISRs genauso.

Rein theoretisch könnte man aus dem Programm die Interrupttabelle neu 
flashen, aber das wäre ein vöölig abstruser Hack. Und abstruse Hacks 
deuten immer darauf hin, daß die Programmstruktur völlig daneben ist.

Wie oben schon geschrieben steht, musst du irgendwo ein Flag setzen, und 
dann in der EINEN ISR in die verschiedenen Funktionen verzweigen.

Oliver

von Dhaza (Gast)


Lesenswert?

Cyblord -. schrieb:
> ir ist immer noch die klar, warum nicht die offensichtliche Lösung
> gewählt wurde: In der ISR wird eine Funktion über einen Funktionszeiger
> aufgerufen.
> Da braucht es keine Unterscheidungen an dieser Stelle.

Das kam etwas durch die Herangehensweise (was nicht sonderlich klug war, 
zugegeben, die Umschaltung war recht kurz entschlossen nachträglich 
hinzugefügt.

Aber so wie im zweiten Teil deiner Antwort werde ich es machen. Ich 
nutze die ISR nur um zum Funktionsaufruf und nehme die Funktionen da 
raus.

von Peter D. (peda)


Lesenswert?

Matthias S. schrieb:
> Du kannst ein Flag setzen, das in der ISR abgefragt wird und dann
> verzweigt.

Oder Du nimmst einen der beiden Compare-Interrupts für die andere 
Funktion.
Es stellt sich natürlich die Frage, warum die Modi unterschiedliche 
Sachen im Interrupt machen sollen.

von Cyblord -. (cyblord)


Lesenswert?

Peter D. schrieb:
> Es stellt sich natürlich die Frage, warum die Modi unterschiedliche
> Sachen im Interrupt machen sollen.

Dass eine ISR Behandlung z.B. vom aktuellen Zustand abhängt ist nicht 
ungewöhnlich.

von Einer K. (Gast)


Lesenswert?

Hier ein Beispiel aus meiner Wühlkiste:
(marginal für deine Zwecke modifiziert)
1
#include <util/atomic.h>
2
#define AtomicSection ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
3
4
5
using FuncPtr = void(*)();
6
7
volatile FuncPtr funcptr = nullptr;
8
9
void funcA()
10
{
11
  // tuwas  
12
}
13
14
void funcB()
15
{
16
  // tuwas  
17
}
18
19
ISR(TIMER0_OVF_vect)
20
{
21
  if(funcptr) funcptr();
22
}
23
24
25
int main() 
26
{
27
  for(;;)
28
  {
29
    AtomicSection funcptr = funcA;
30
    // tuwas
31
    AtomicSection funcptr = funcB;
32
    // tuwas
33
    AtomicSection funcptr = nullptr;
34
    // tuwas
35
  }
36
}
Ist zwar C++, aber der Umbau auf C sollte trivial sein.
Ob das volatile nötig ist, überlasse ich deiner Entscheidung.

von Peter D. (peda)


Lesenswert?

Arduino Fanboy D. schrieb:
> Hier ein Beispiel aus meiner Wühlkiste:

Sonderlich effizient ist sowas aber nicht. Der Compiler sichert dann 
erstmal sämtliche Scratchpad-Register.

von Cyblord -. (cyblord)


Lesenswert?

Peter D. schrieb:
> Arduino Fanboy D. schrieb:
>> Hier ein Beispiel aus meiner Wühlkiste:
>
> Sonderlich effizient ist sowas aber nicht. Der Compiler sichert dann
> erstmal sämtliche Scratchpad-Register.

Darüber sollte man sich nur aus Ausnahmefällen Gedanken machen. Eine 
Optimierung auf sauberen C-Code ist besser als ein Optimierung auf 
Controller internas. Zumindest abseits des 0.1% Einzelfalls.

von Einer K. (Gast)


Lesenswert?

Peter D. schrieb:
> Der Compiler sichert dann
> erstmal sämtliche Scratchpad-Register.
Ja, das tut er.

Das tut er immer, wenn das inlineing der, in der  ISR aufgerufenen, 
Funktion nicht möglich ist.

Das "Flag setzen und in der ISR auswerten" scheint dem TE ja nicht zu 
schmecken.
Dann hat er halt diese Kröte zu schlucken.
Ganz so viele Alternativen scheints ja nicht zu geben.

von c-hater (Gast)


Lesenswert?

Cyblord -. schrieb:

> Das erfordert auch keinen Unsinn mit der ISR selber. Es kommt halt ein
> Funktionsaufruf hinzu.

Der kann recht teuer kommen. Schon der Funktionsaufruf selber ist nicht 
ganz billig, insbesondere auf den größeren AVR8 mit mehr als 128kB 
Flash.

Das Sichern und Wiederherstellen etlicher Register kommt dann noch dazu.

Selbst in Asm vermeide ich es, wo immer möglich, indirekte calls zu 
verwenden. Insbesondere natürlich in ISRs.

von leo (Gast)


Lesenswert?

c-hater schrieb:
> Der kann recht teuer kommen. Schon der Funktionsaufruf selber ist nicht
> ganz billig,

Ich kann mich immer nur wundern, warum die Leute glauben, das Zeug sei 
langsam. Ich haette vor 40 Jahren nie Text auf den Z80/8085 usw. 
schreiben koennen ;-) Auch die kleinen Tinys sind schon vielfach 
schneller.

leo

von c-hater (Gast)


Lesenswert?

leo schrieb:

> Ich kann mich immer nur wundern, warum die Leute glauben, das Zeug sei
> langsam.

Es ist langsam!

> Ich haette vor 40 Jahren nie Text auf den Z80/8085 usw.
> schreiben koennen ;-)

Du scheinst nicht verstanden zu haben, dass es auch viele Anwendungen 
für µC gibt, die vielfach schneller auf äußere Ereignisse reagieren 
können müssen, als die, welche menschliche Eingaben auszulösen in der 
Lage sind...

von leo (Gast)


Lesenswert?

c-hater schrieb:
>> Ich kann mich immer nur wundern, warum die Leute glauben, das Zeug sei
>> langsam.
>
> Es ist langsam!

Ich lese oben "LED", "Schalter", ...

wie du meinst...

leo

von Stefan F. (Gast)


Lesenswert?

Dhaza schrieb:
> Dass ich je Modus eine andere ISR(TIMER0_OVF_vect) brauche

Brauchst du nicht. Deine ISR kann je nach Modus eine andere Funktion 
aufrufen. Alternativ zu Funktionszeigern geht es auch so:
1
switch (modus)
2
{
3
  case 1: isr_modus1(); break;
4
  case 2: isr_modus2(); break;
5
  case 3: isr_modus3(); break;
6
  case 4: isr_modus4(); break;
7
}

von Einer K. (Gast)


Lesenswert?

Das kann effizienter sein, wenn der Compiler die Funktionen inline 
einbaut.
Ansonsten halt auch nicht.

von c-hater (Gast)


Lesenswert?

leo schrieb:

> Ich lese oben "LED", "Schalter", ...

So what? Selbst in wirklich richtig kritischen Anwendungen kommen fast 
immer irgendwelche Schalter/Taster und LEDs vor. Das eine ist die 
eigentliche Aufgabe des µC, das andere das "GUI" zu seiner 
Konfiguration/Parametrierung.

Insofern: Die Existenz eines GUI ist ja wohl kein sicheres 
Ausschlußkriterium für eine zeitkritische Aufgabe des µC...

Aber die obersten Glaskugel-Besitzer haben wohl tiefergehende 
Informationen zur Intention des TO...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Cyblord -. schrieb:
> Ich hoffe es gibt in der Hölle eine ganz spezielle Ecke für Leute die
> Quellcode als Bild posten.

Ok, also doch besser als Video.

von Stefan F. (Gast)


Lesenswert?

Johann L. schrieb:
>> Ich hoffe es gibt in der Hölle eine ganz spezielle Ecke für Leute die
>> Quellcode als Bild posten.
> Ok, also doch besser als Video.

Meinst du so: https://www.youtube.com/watch?v=IYlOQU6euZs ?

Der Typ fordert seine Follower auf, das Video auszudrucken.

von c-hater (Gast)


Lesenswert?

Cyblord -. schrieb:

> Ich hoffe es gibt in der Hölle eine ganz spezielle Ecke für Leute die
> Quellcode als Bild posten.

Ja gibt es, ist aber noch nicht richtig durchdacht.

Die gegenwärtige Imlementierung ist: Alle Bits von geposteteten Anhängen 
werden als Matrix repräsentiert, wobei jedes gesetzte Bit durch einen 
10"-Nagel repräsentiert wird. Der Sünder wird nun über alle 
Kombinationen dieser Bits gezogen.

Der Implementierungsfehler ist: verglichen mit der Ewigkeit ist die 
Strafe viel zu schnell abgeritten...

Der Teufel verflucht die Endlichkeit binärer Mathematik!

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.