Hallo an Alle, ich bin neu in diesem Forum und programmiere auf einem Atmel 89S8252 in Assembler.(bin noch Anfänger) Ich möchte eine PWM generieren mit Hilfe von Timer0 und Timer1. - beide Timer laufen im Betriebs-Modus2 - Timer0 wird mit 0 nachgeladen - in der INT von Timer0 wird TH1 z.b. mit 128 vorgeladen,das Timerrunbit von Timer1 gesetzt und mein Portpin (der die PWM ausgibt) mov TH1,PWM_Value setb TR1 setb PWM_Out - in der INT von Timer1 wird das Timerrunbit von Timer1 und der Portpin für die PWM gelöscht clr TR1 clr PWM_Out Das ganze funktioniert super so lange ich TH1 mit einem Wert von 255-15 vorlade. Bei Werten von 14-0 habe ich nicht nur kurze Ausschaltimpulse sondern auch lange dazwischen. z.B. 3x kurz ok und dann aber 1x lang dann wieder 3x kurz (ganz symetrisch). Bei anderen Werten zwischen 0-14 kommt ein völlig vermatschtes Signal am Portpin an. Wieso ist das so? Gruß Tommy
Ich könnte mir vorstellen, dass bei 0-14 deswegen Müll rauskommt, weil dann der Timer-Interrupt schneller kommt als die Interrupt-Routine dauert. Das heisst, die Zeit zum Abarbeiten der Interrupt-Routine ist größer als der eingestellte Timer-Interrupt. Das könnte einen Stack-Überlauf bewirken. Setzt du im Timer1-Interrupt auch das TR0-Bit? Oder läuft ein Timer ständig? Warum machst du das mit zwei Timern? Nimm doch nur einen Timer und zwei 1-Byte-Variablen. Eine Variable ist die ON-Zeit, die andere die OFF-Zeit. Welche Variable du ins Reload-Register lädst, kannst du abhängig machen vom aktuellen Zustand des Ausgangs-Pins. Die Summe beider Variablen ist logischerweise die Frequenz der PWM. Vorteil dieser Art wäre meiner Meinung nach,dass du einen Timer sparst, und dass du einen größeren Bereich abdecken kannst. Ralf
Das ganze funktioniert nur so lange, wie der T1-Int. früher als der von Timer0 kommt. Beim Überlauf von T0 werden in der ISR 4 Befehle ausgeführt: mov TH1, PWM_value (2 Zyklen) setb TR1 (1) setb PWM-out (1) Reti (2) Währenddessen ist Timer0 aber schon bei 6 --> wenn TH1 mit einem hohen Wert geladen wird, kommt Timer1 zu spät.
>wenn TH1 mit einem hohen Wert geladen wird
muß natürlich "mit einem niedrigen Wert" heißen
@Jack: Deswegen mein Vorschlag, nur einen Timer mit zwei verschiedenen Variablen zu verwenden... Ralf
@Ralf: Deinen Beitrag hab ich erst gesehen nachdem ich meinen abgeschickt hatte. Natürlich kann man es mit einem Timer machen, der Vorteil bei zwei liegt aber in der höheren Frequenz und in der einfacheren Steuerung. Die Randbereiche (sehr kurze on- und off-Zeit) braucht man sowieso nicht. Ich hab damit eine Funkfernsteuerung für eine Märklin-Lok gemacht (Spur 1).
Ich hätte hier noch ne PWM-Version, die sehr schnell ist: http://home.tiscali.de/peterd/appl/soft/c51/pwm/index.htm Peter
Hallo, erstmal danke für die Hilfe von euch! @Ralf: Ne ich setze das TR0-Bit nicht im Timer1-Interrupt - der Timer0 läuft ständig. Finde deinen Vorschlag mit nur einem Timer echt gut werde das gleich mal ausprobieren. @Jack: Danke dir für die ausführliche Erkärung jetzt ist mir klar warum das nicht funktioniert. @Peter: Dank dir auch für deinen Link leider war das Beispiel nur in C und nicht in Assembler. Nochmal danke. Gruß Tommy
@Thomas: Wichtig ist bei der Ein-Timer-Lösung, dass du niemals einen Reload-Wert einsetzt, der den Timer schneller auslöst als die Interrupt-Routine dauert. Sonst bekommst du einen Stack Overflow. Ralf
"Sonst bekommst du einen Stack Overflow." Nein, sowas geht beim 8051 nicht ! Du kannst maximal soviel Interrupts kellern, wie Du Interruptprioritäten benutzt, dann ist definitiv Schluß. Die Hardware zählt die RETIs mit. Ohne RETI, kein neuer Interrupt gleicher oder niederer Priorität. Sehr clever und sehr sicher dieser 8051. Peter
@Peter: Oh verflixt, stimmt ja... Hab ich ganz vergessen... Sorry... Ralf
Hallo, @Ralf: Ja dann kommt da warscheinlich wieder so ein vermatschtes Signal raus wie ich es schon hatte. @Peter: Aber merkt sich der MC denn nicht wenn ein zweiter INT ausgelöst wird? Wenn ich die Funktionen von INTs richtig verstanden habe kann ein INT höherer Priorität einen niedrigeren unterbrechen und im Anschluss wird der niedrigere weiter abgearbeitet oder? Und wenn ein INT gleicher Priorität kommt merkt der MC sich das nicht? z.B. Timer0 INT wird ausgelöst und während dieser abgearbeitet wird kommt der Timer1 INT (beide die gleiche Priorität)geht mir dann Timer1 INT verloren? Sorry für die vielen Fragen aber als Anfänger ist das alles nicht so einfach. Danke euch für die klasse Hilfe! Gruß Tommy
Nein, es geht dir nichts verloren. Timer 0 ist von sich aus schon höher priorisiert als Timer 1. Das heisst, wenn du die Prioritäten nicht änderst, darf Timer 0 immer. Bezüglich Interrupts gleicher Prioritäten, der aktuelle Interrupt wird nicht deswegen unterbrochen, aber der Controller merkt sich, dass da noch ein Interrupt abgearbeitet werden soll, und startet nach Ablauf der letzten Interrupt-Routine gleich die nächste Interrupt-Routine. Geht also nix verloren. Guck mal hier, vielleicht hilft dir das auch noch: http://www.atmel.com/dyn/resources/prod_documents/doc0509.pdf http://www.atmel.com/dyn/resources/prod_documents/doc4316.pdf Im Kapitel 2.16 vom Hardware Manual steht die Sache mit den Interrupts erklärt. Da steht auch, wie es funktioniert, wenn zwei gleich priorisierte Interrupts gleichzeitig auftreten, und welcher von denen dann zuerst abgearbeitet wird... HTH Ralf
"Aber merkt sich der MC denn nicht wenn ein zweiter INT ausgelöst wird?" Jede Interruptquelle hat ein Interrupt-Pending-Flag und solange dieses gesetzt ist, wird der Interrupthandler angesprungen, sobald es erlaubt ist und wenns 10 Jahre dauert. Man muß Interruptquellen auch nicht als Interrupts bearbeiten, sondern kann auch auf dieses Flag pollen und dann die entsprechende Funktion aufrufen (z.B. UART im Polling-Mode). Peter
Hallo, danke für die super Unterstützung! So mach es noch mehr Spaß. Ich hoffe ich darf in Zukunft euch mal wieder mit meinen Anfängerfragen nerven. Gruß Tommy
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.