Hallo, auf meinem ATmega328 Arduino gehen mir die Timer aus. Bisher habe ich vermieden Timer0 zu verwenden, weil Arduino es für einen Zähler einsetzt um z.B. die delay() Funktion zu realisieren. Der Timer0 erzeugt 976,56 mal pro Sekunde einen Interrupt zu einer Arduino Funktion, die die Zeit aufaddiert. Ich würde mich jetzt gerne vor die Arduino Intterupt Routine setzen. Also den Originalvektor der Arduino Routine sichern und durch meine eigene Funktion ersetzen. Nun meine Befehle in der neuen Interrupt Funktion abarbeite und dann wieder in den Vektor von Arduinos Interruptroutine zurückspringen. Weiß jemand ob und wie das geht? Beste Grüße stero
Wenn du viele Timer brauchst verwende doch Software-Timer. Hänge dich in irgendeine ISR bei der die die Zeitkonstante gerade gut passt und rufe dort (am besten kurz bevor die ISR verlassen wird) eine Funktion "Tick()" auf. In der kannst du dann beliebig viele neue Timer erstellen:
1 | uint16 u16_Timer1 = 0xFFFF; |
2 | |
3 | void Tick(void) |
4 | {
|
5 | if( u16_Timer1 == 0xFFFF ) |
6 | {
|
7 | //mache nix da der Timer nicht gestartet ist.
|
8 | //zu starten den Timer1 auf einen Wert <0xFFFF setzen
|
9 | }
|
10 | else
|
11 | {
|
12 | //Timer1 läuft
|
13 | if( u16_Timer1 > 0 ) |
14 | {
|
15 | //Timer ist noch nicht abgelaufen
|
16 | u16_Timer1--; |
17 | }
|
18 | else
|
19 | {
|
20 | //Timer ist abgelaufen..
|
21 | //irgend ne Funktion oder Makro aufrufen:
|
22 | timeout_Timer1(); |
23 | //oder auch ne variable setzen und die dann pollen:
|
24 | b_timeout_Timer1 = TRUE; |
25 | }
|
26 | }
|
27 | |
28 | //Timer 2, 3, 4, usw. :
|
29 | }
|
Hallo Benjamin, vielen Dank für deine Antwort. Ich benutze nicht alle Timer um Interrupts auszulösen, sondern um direkt ohne Interruptaufruf die Ausgangspins zu toggeln. Wenn da jedesmal ein Intterruptvektor angesprungen werden müßte, wäre das leider zu Rechenzeitaufwendig. Man könnte vielleicht versuchen den Interrupt schneller zu machen, als der Originalcode von GCC. Der macht allerhand zeitfressende Sicherungen vor und nach der Interruptroutine. Aber da begibt man sich natürlich auf dünnes Eis, wenn man das alles selber machen will.
ja, es kommt natürlich drauf an welche Zeiten du benötigst und wie schnell dein uC taktet. es hängt von der Größe deiner Interrupt-Vektor-Tabelle ab ob du vor dem Aufruf der ISR noch platz hast um einen Ausgang zu toogeln. Bei den meisten AVRs dürftest du da schlechte Karten haben. Es gibt allerdings bei gcc einen Befehl bzw. eine #pragma Anweisung um eine leere ISR zu erstellen, d.h. es werden keine Register gesichert und zurück geschrieben. Wenn du also weiß das du keine Register veränderst kannst du das nehmen, dann bist du in 2-3 Takten in dem Code. Wenn das Ausgang toogeln sehr schnell sein muss, die "ursprüngliche" ISR aber nicht kannst du eine leere ISR erstellen, deinen Ausgang setzen, dann die Register manuell sichern, dann die "ursprüngliche" ISR Aufrufen, dann die Register zurückschreiben und die ISR verlassen.
Hallo Benjamin, das mit dem Toggeln kann der ATmega ja auch ganz ohne CPU Belastung. Ich nutze den "clear on compare match" Modus von Timer2 und die PWM Ausgabe auf dem dazugehörigen OC2B-Pin. Ich probiere noch einen anderen Weg, indem ich direkt die Arduino Bibliothek mit dem original Interruptaufruf erweitere. Als letzten Befehl schreibe ich in die original Arduiono Timer0 ISR Routine einen Funktionsaufruf an eine über Funktionspointer einstellbare Funktion. Diese Funktion kann ich dann hoffentlich - wenn es endlich mal klappen würde - aus dem Hauptprogramm heraus auf meine Erweiterung der Timer0 ISR zeigen lassen. Eigentlich sollte es klappen, aber er schreibt mir immer eine Fehlermeldung mit "undefined reference". Ich arbeite daran... :]
Hallo Benjamin, hier gibt es Auswertungen zu den von dir Vorgeschlagenen kurzen Interruptzeiten: http://www.embeddedrelated.com/usenet/embedded/show/1437-1.php Wie man das viele gepushe und gepoppe verringern kann steht hier im Abschnitt "ISR mit eigenem Prolog/Epilog": http://www.rn-wissen.de/index.php/Avr-gcc Im Folgenden der interessante Abschnitt daraus. Ich hoffe der Autor vergibt mir die ungefragte Kopie: ______________________________________________________________ Wenn man in einer ISR komplett eigenes Zeug machen will, dann definiert man eine nackte Funktion. Mit naked befreit man die Routine vom Standard-Prolog/Epilog. Dabei ist darauf zu achten, daß die ISR mit reti (return from interrupt) zurückkehrt und evtl. verwendete Register und den Status (SREG) sichert. #include <avr/io.h> void _attribute_ ((naked)) SIG_OVERFLOW0 (void) { // Port B.6 = 0 // Diese Instruktion verändert nicht das SREG und kein anderes Register // so daß der eigentliche Code nur 1 Befehl lang ist _asm_ __volatile ( "cbi %0, %1" "\n\t" "reti" : : "M" (_SFR_IO_ADDR (PORTB)), "i" (6) ); }
Stephan R. schrieb: > Diese Funktion kann ich dann hoffentlich - wenn es endlich mal klappen > würde - aus dem Hauptprogramm heraus auf meine Erweiterung der Timer0 > ISR zeigen lassen. Wenn du direkt in der IVT verzweigen willst dürfte die Größe der IVT nur ausreichen wenn du das Register-Paar das der IJMP Befehl verwendet dauerhaft für die Adresse der jeweiligen ISR reservierst. Lohnt sich IMO nicht nur um den Sprung in eine naked-ISR einzusparen.
Benjamin F. schrieb: > Wenn du direkt in der IVT verzweigen willst dürfte die Größe der IVT nur > ausreichen wenn du das Register-Paar das der IJMP Befehl verwendet > dauerhaft für die Adresse der jeweiligen ISR reservierst. > Lohnt sich IMO nicht nur um den Sprung in eine naked-ISR einzusparen. Indem ich mich hinter die ohnehin vorhandene Arduino Timer0 Interruptroutine hänge, nutze ich, das bereits alle Register gesichert und restauriert werden. Bis auf das Anspringen und Zurückspringen zu meiner ergänzenden Interruptroutine entsteht kein Overhead und das, ohne sich über Register auf Assembler Ebene Gedanken machen zu müssen. Wichtig für meine Anwendung ist aber besonders, das ich die anderen beiden Timer für andere Aufgaben frei behalte. Die Lösung, durch Ändern der Original Arduino Dateien sich hinter die Arduino Timer0 Interruptroutine zu hängen, funktioniert jetzt. Ich habe im Arduino Forum meine modifizierte wiring.c und Arduino.h Datei eingestellt. Aufgerufen wird das sehr bequem direkt aus dem Sketch. Neben diesen zwei Dateien habe ich auch ein kleines Beispiel gemacht, wie man es aus dem Sketch aufruft: http://arduino.cc/forum/index.php?topic=87945.0 VG Stephan
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.