mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 89S8252 PWM mit Timer generieren


Autor: Thomas Fuchs (tommy_fux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Cri Gri (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab auch interesse an diesem Beitrag!

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jack Braun (jackbraun)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Jack Braun (jackbraun)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>wenn TH1 mit einem hohen Wert geladen wird
muß natürlich "mit einem niedrigen Wert" heißen

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jack:

Deswegen mein Vorschlag, nur einen Timer mit zwei verschiedenen
Variablen zu verwenden...

Ralf

Autor: Jack Braun (jackbraun)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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).

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hätte hier noch ne PWM-Version, die sehr schnell ist:

http://home.tiscali.de/peterd/appl/soft/c51/pwm/index.htm


Peter

Autor: Thomas Fuchs (tommy_fux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"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

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:

Oh verflixt, stimmt ja... Hab ich ganz vergessen...
Sorry...

Ralf

Autor: Thomas Fuchs (tommy_fux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Ralf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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/...
http://www.atmel.com/dyn/resources/prod_documents/...

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

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"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

Autor: Thomas Fuchs (tommy_fux)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.