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?
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:
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.
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.
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:
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...
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!