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?
Ich hoffe es gibt in der Hölle eine ganz spezielle Ecke für Leute die Quellcode als Bild posten.
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!
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.
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
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.
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
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!
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
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.
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.
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.
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.
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.
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.
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.
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.
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
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...
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
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 | }
|
Das kann effizienter sein, wenn der Compiler die Funktionen inline einbaut. Ansonsten halt auch nicht.
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...
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.