Hallo, ich will zwei verschiedene Signale mit Timer0 und Timer2 bei einem Atmega48 in C erzeugen. Die Signale sollen jeweils 9 unterschiedliche Impulslängen besitzen. Die Signale hab ich hinbekommen und Sie funktionieren einzeln wunderbar. Nur wenn ich beide Timer in einem Programm laufen lasse besitzt das Signal von Timer0 einen Fehler! Genauer gesagt, der dritte Impuls des Signals spinnt rum, schaltet immer zwischen Low- und Highpegel hin und her. Kann es sein dass sich die Timer irgendwie gegenseitig beeinflussen, bzw. stören? Hab das Programm mal angehangen....
Mist zu früh abgeschickt. Wollte schreiben: Setz mal in der Timer ISR nur ein Flag und mach die Aktion im Hauptprogramm (zumindest bei dem Timer wo du soviel rumrechnest!)
Aber ich rechne doch in beiden Timern gleich viel. Bei Timer2 funktioniert es ja auch, nur bei Timer0 hat das signal einen Fehler. Wenn ich Timer0 mal alleine in dem Programm laufen lasse, ist das Signal völlig in Ordnung. Nur wenn beide Timer gleichzeitig laufen, taucht das Problem auf.
Ich wollte sagen: wenn du in einer ISR viel rechnest mußt dus ins Hauptprogramm verlagern. Sosnt kannst du das Problem haben: T0 kriegt interupt rechnet rechnet rechnet T1 erzeugt Interupt, da T0 aber noch nicht fertig ist wird erstmal gewartet auf T0, jezt ist T0 fertig, T1 darf rechnen aber inzwischen sind schon wieder interupts für T1/T0 aufgelaufen... Da aber immer nur ein Interupt abgearbeitet wird kannst du interupts verlieren. Ein anderes Problem könnte sein das Variablen die in einer ISR verwendet werden mit voiltaile deklariert werden müssen, das sit jezt aber nur "gelesenes Wissen" da ich selber in ASM programmiere.
@Läubi: Variablen müssen im Prinzip nur dann volatile deklariert werden, wenn sie im Hauptprogramm verwendet werden, aber auch in ISRs verändert werden können. Ansonsten stimme ich zu: Mach die ISR so kurz wie möglich. Ich weiß jetzt nicht, wie groß die Wahrscheinlichkeit ist, dass beide Interrupts gleichzeitig auftreten (oder dass während der Ausführung einer ISR beide Interrupts erneut auftreten), aber wenn das der Fall sein sollte, wird die Timer2-ISR bevorzugt ausgeführt, da Timer2 die höhere "Priorität" besitzt. Da kann es durchaus vorkommen, dass Timer 0 ins Hintertreffen gerät.
Ist es nicht irgendwie möglich, während der eine Interrupt läuft den anderen auszuschalten und danach wieder einzuschalten? Hab gerade mal versucht, es ohne ISR zu machen, also in der main(). Nur das klappt gar nicht.
>Ist es nicht irgendwie möglich, während der eine Interrupt läuft den >anderen auszuschalten und danach wieder einzuschalten? Das passiert sowieso grundsätzlich beim AVR. Wäre dein Programm etwas besser kommentiert, könnte man vielleicht sogar einen Vorschlag machen, wie man es verbessern könnte. Was soll das Ding überhaupt machen?
Hey, hab das Programm mal neu kommentiert und beschrieben. Befindet sich im Anhang. Wäre super wenn einer mal schauen könnte und vielleicht ne Idde hat wie man das Problem lösen kann, komm nämlich echt nicht weiter.
erste Verbesserung: statt if(NrOverflow_Servo2 % 2 == 0) geht auch if (!(NrOverflow_Servo2 & 1)) Wenn NrOverflow_Servo2 nicht ungerade ist, wird Port ausgeschaltet, sonst eingeschaltet. Wenn man die Anweisung aus den Entscheidungszweigen vertauscht müsste auch if (NrOverflow_Servo2 & 1) gehen. Wegen der Timer habe ich noch eine Idee, die aber noch nicht ganz ausgeklügelt ist...(es hat mit dem fast PWM-Mode zutun...)
Danke erst ein mal für die Tips! Wäre super wenn einer noch ne Idee für den Timer hätte, bin schon echt verzweifelt! Häng nun schon seid 6 Stunden davor und kries einfach nicht hin.
Der Unterschied zwischen dem CTC- und dem fPWM-Mode ist, dass der fPWM-Mode gepuffert ist. Das bedeutet, dass man dem Timer schon einen neuen TOP-Wert übergeben kann, ohne dass ihn dieser in dem Moment interessiert. Beim CTC wird TOP sofort überschrieben. Damit könnte man die ISR vereinfachen, in dem dort nur noch ein Zähler hocgezählt wird, und der Portpin umgeschaltet wird (und setzt ein Flag). In der Hauptschleife vergleicht man entweder einfach den aktuellen Feldindex mit dem letzten, und schreibt den neuen Wert ins OCR, oder reagiert ebenso auf das gesetzte Flag. In der Schleife kann man dann auch noch einen Feldindex-Überlauf überwachen. Könnte so funktionieren...
Hi Rahul, leider haut es so bei mir auch nicht hin. Brauch jetzt erst mal ne Pause, seh schon gar nichts mehr. Werd es dann gleich noch mal versuchen. Gibt es denn noch irgend ne andere Möglichkeit?
>Der Unterschied zwischen dem CTC- und dem fPWM-Mode ist, dass der >fPWM-Mode gepuffert ist. Das bedeutet, dass man dem Timer schon >einen neuen TOP-Wert übergeben kann, ohne dass ihn dieser in dem >Momentinteressiert. Beim CTC wird TOP sofort überschrieben. >Damit könnte man die ISR vereinfachen, in dem dort nur noch ein >Zähler hocgezählt wird, und der Portpin umgeschaltet wird (und >setzt ein Flag). >In der Hauptschleife vergleicht man entweder einfach den aktuellen >Feldindex mit dem letzten, und schreibt den neuen Wert ins OCR, oder >reagiert ebenso auf das gesetzte Flag. >In der Schleife kann man dann auch noch einen Feldindex-Überlauf >überwachen. Kapier ich nicht, bzw. ich krieg es nicht hin! Kannst du mir das noch mal etwas genauer erklären?
Noch genauer? Was denn genau? Wenn man im CTC-Mode das Register ändert, das für den TOP-Wert verantwortlich ist, dann kann es passieren, dass der neue Wert kleiner als der aktuelle Zählerwert ist. Das führt dazu, dass der Timer komplett bis 0xFFFF durchläuft und dann erst wieder Chance hat, den Vergleichswert zu erreichen. Es ist kein "Timer >= TOP?"-, sondern ein "Timer == TOP?"-Vergleich. Bei fPWM-Mode (fast PWM) wird der TOP-Wert erst aktualisiert, wenn der zuvor gewählte erreicht wurde. Man kann also während der Timer sein "Programm" (zähle bis TOP) abarbeitet, ihm den nächsten "Programmpunkt" (neues TOP) mitteilen. Zu meiner ISR-Methode: Muß ich noch mal genauer drüber nachdenken (und es mir vielleicht auch noch aufmalen...)
Ist es denn nicht möglich, die Signale hintereinander zu erzeugen. Also dass der eine Interrupt erst startet wenn der andere mit der Erzeugung des Signals fertig ist. Der hat dann solange Pause bis der andere fertig ist und dann immer hin und her. Irgendeine Idee in diese Richtung...?
Willst du Signale für zwei Servos erzeugen? Du kannst es natürlich so machen, dass der zweite Timer erst losläuft, wenn der erste seine komplette Sequenz abgearbeitet hat (und andersherum). Dann könnte man das aber auch mit nur einem Timer realisieren.
Das hab ich mir jetzt auch gerade gedacht. Eigentlich kann ich doch beide Signale in einer ISR hintereinander erzeugen..... Mal ausprobieren!
Würde gerne ne doppelte Bedingung in die if-Anweisung einbauen? Etwas wie if(Count <= 17 & >=34) ? Wie kann ich das schreiben?
Danke! Hab es jetzt soweit hinbekommen. Die Signale sehen ganz gut aus. Nur im zweiten Signal läuft irgendwie noch mal ein Impuls durch. Kann es da sein, dass es irgendwie noch Teile vom ersten Signal bekommt? Hab den Code noch mal angehangen. Wäre super wenn du ihn dir noch mal anschauen könntest
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.