Hi Leute, kurz zu meinem Problem, ich möchte mit einem ATmega8 und 3.686400 MHz Quarz einen Timer realisieren und wenn 10 sekunden verstrichen sind, dann soll ein flag gesetzt werden, es sei denn innerhalb dieser 10sekunden findet in der ISR(INT0_vect) eine Retriggerung bzw reset des Timers statt. Wie gehe ich da am besten vor und welchen TimerInt verwende ich da am besten, ich steig durch die vielen Modis der Timer nicht wirklich durch... Von mir aus kann die TimerISR so oft wie nötig aufgerufen werden, aber nach 10sekunden (ohne Timerreset) soll ein flag in der TimerISR gesetzt werden. Allerdings benutze ich auch parallel die UART und dummerweise habe ich hier neulich einen Beitrag gelesen, dass der Timerinterrupt eventuell die UART stört? Mit welchem Modus wäre ich auf der sicheren Seite, ohne unnötig "hochfrequente" Timerinterrupts auszulösen??? Besten Dank, schönen Feierabend und LG Spice
Falscher Ansatz, das direkt mit dem Timer machen zu wollen. Du benutzt den Timer als Zeitgeber, der zb. alle 1/100 Sekunde eine ISR auslöst. In der ISR zählst du eine Variable hoch. Hat die Variable den Wert 1000 erreicht, sind vom Starten des Timers an gerechnet 10 Sekunden vergangen. Willst du den Timer resetten, setzt du die Variable einfach wieder auf 0 zurück. Das Auswerten der Variablen machst du in der ominösen Hauptschleife in main(). D.h. die Timer-ISR zählt einfach nur die Variable hoch und sonst nichts. > habe ich hier neulich einen Beitrag gelesen, dass > der Timerinterrupt eventuell die UART stört? Das tut er nur, wenn die Timer-ISR zu lange dauert. Da du dich aber brav an die Konvention hältst, dass eine ISR nur das Allernotwendigste machen soll, und alles andere in die Hauptschleife ausgelagert wird, kann dir das nicht passieren.
Vielen Dank für die Hilfe, genau in der art meinte ich das eigentlich auch, nur dass halt keine 100 INTs in der Sekunde ausgelöst werden, sondern bissl weniger vielleicht (damit die Uart nicht gestört wird) Aber da ja nix gestört werden soll, wenn meine ISR "nur" zählt, werde ich da so vorgehen. Allerdings habe ich noch eine Frage zu >Das Auswerten der Variablen machst du in der ominösen Hauptschleife in >main(). D.h. die Timer-ISR zählt einfach nur die Variable hoch und sonst >nichts. Ich habe in meinem Code eine Funktion (nicht MAIN), die auswerten soll, ob der Timerwert erreicht wurde. Stellt das ein Problem dar? Spielts es eine Rolle, wo geprüft wird, wenns nicht gerade in der ISR selbst ist? Wenn nun beispielsweise meine Funktion zum auswerten der Hilfsvariable eine "kleine" UART routine mit enthält, wo eine Zeichenkette ausgegeben wird und diverse PORTs geschaltet werden. Kann es sein, dass mein Programm zu lange braucht, bis an die eigentliche Prüfstelle zb void foo(void) { ....... if (hilfsvariable==1000) { .... ; hilfsvariable = 0; } ... } zu gelangen und ich sozusagen genau die 1000 nicht abgefragt bekomme bzw "verpasse" ??? Ist es hier sinnvoller mit if (hilfsvariable >=1000) abzufragen, da der Wert der Hilfsvariable ja in der Zeit, bis mein Programm es prüft, um 1 (oder mehr inkrementiert) worden sein kann? Würde mich über weitere Hilfe sehr freuen MFG Spice
keine Timergurus unterwegs?
Spice wrote: > nur dass halt keine 100 > INTs in der Sekunde ausgelöst werden, sondern bissl weniger vielleicht > (damit die Uart nicht gestört wird) Vergiss die UART. Die UART wird von einem Timer nicht gestört. Und vergiss auch die Vorstellung, dass dir 100 Interrupts in der Sekunde grossartig viel Rechenzeit kosten. Wenn in der ISR lediglich eine Variable hochgezählt wird, dann bewegt sich der prozentuelle Rechenzeitverbrauch dafür bei winzigen Prozentbereichen. Nichts worüber du dir Gedanken machen musst. In Timing-Probleme kommt man erst dann, wenn in einer ISR viel zu viel passiert, wie zb irgendwelche Ausgaben auf LCD oder UART. > Ich habe in meinem Code eine Funktion (nicht MAIN), die auswerten soll, > ob der Timerwert erreicht wurde. Stellt das ein Problem dar? Sollte egal sein. > Spielts es > eine Rolle, wo geprüft wird, wenns nicht gerade in der ISR selbst ist? Völlig wurscht. > Wenn nun beispielsweise meine Funktion zum auswerten der Hilfsvariable > eine "kleine" UART routine mit enthält, wo eine Zeichenkette ausgegeben > wird und diverse PORTs geschaltet werden. Kann es sein, dass mein > Programm zu lange braucht, bis an die eigentliche Prüfstelle zb Das könnte allerdings sein. Bei der UART Ausgabe muss ja unter Umständen gewartet werden, bis die UART wieder frei ist. Dann muss halt in diese Warteschleife ebenfalls eine ABfrage rein. > > void foo(void) > { > ....... > if (hilfsvariable==1000) Machs eher so if (hilfsvariable >= 1000) Der Unterschied: Wenn du in deinem Code an irgendeiner Stelle zu lange gebraucht hast und der Timer schon um 1 weiter gezählt hat, dann ist in deiner Version der Teufel los. Fragst du aber sicherheitshalber auf größer ab, dann stimmt zwar das Timing nicht mehr ganz 100%, aber zumindest kommt es nicht zu einem extremen Timingfehler, weil hilfsvariable einmal rundum zählen muss, bis das nächste mal wieder 1000 auftaucht.
Vielen Dank für die kompetente Hilfe... eine Frage noch, welchen Modus nehme ich am besten am Atmega8? Besten Dank und gruß Spice
Spice wrote: > Vielen Dank für die kompetente Hilfe... > eine Frage noch, welchen Modus nehme ich am besten am Atmega8? Im Grunde ist es völlig egal. Wenn ich keine besonderen Anforderungen an den Timer habe, nehm ich gerne den stinknormalen Modus mit Overflow-Interrupt. Die viel wichtigere Frage lautet ja: welchen Vorteiler nehm ich? Dazu muss man ein bichen rechnen und probieren. Mal angenommen du nimmst den Timer0. Dann kriegst du nach jeweils 256 Timer Ticks einen Overflow. Wie setzt du nun den Vorteiler, so dass du damit was vernünftiges anfangen kannst? Du möchtest ja möglichst genau eine bestimmte Zeit abzählen. Mal angenommen du nimmst 1024 als Vorteiler, dann kriegst du 3686400/256/1024 = 14.0625 Interrupts in der Sekunde. Nicht berauschend. Die Nachkommastellen verhindern, dass du einfach auf eine ganzzahlige Anzahl an Interrupt-Aufrufen wartest um 1 Sekunde abzuzählen. Und auf 0.0625 Interrupts kann man nun mal nicht warten Anderer Vorteiler: 3686400/256/256 = 56.25 genauso schlecht Was ist mit 64? 3686400/256/64 = 225.0 Bingo! Geht sich genau aus. Bei einem Vorteiler von 64 entstehen exakt 225 Overflows in der Sekunde. Damit wär für mich die Sache klar: Timer0, Vorteiler 64, Overflow-Interrupt Willst du nur ganze Sekunden zählen? Wenn ja, dann sieht die Overflow Routine so aus ....
1 | volatile uint8_t Sekunden; |
2 | uint8_t TickCnt = 0; |
3 | |
4 | ISR( .... ) |
5 | {
|
6 | TickCnt++; |
7 | if( TickCnt == 225 ) { |
8 | TickCnt = 0; |
9 | Sekunden++; |
10 | }
|
11 | }
|
... und je nachdem wie genau dein Quarz tatsächlich auf 3686400Hz schwingt, erhöht sich die Variable Sekunden tatsächlich im Sekundentakt.
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.