Hallo!
Bin gerade am Experimentieren mit einem 8051-Mikrocontroller-Board.
Möchte eine LED per PWM mit wechselndem Tastgrad an und aus "dimmen".
Klappt so weit eigentlich auch, nur gibt es an dem Punkt, an dem die LED
kurz ausgeschaltet sein sollte, einen kurzen, sehr hellen Impuls.
Ich schätze der µC hat einfach Probleme, eine PWM mit Duty-Cycle nahe 0%
zu liefern? Gibt es einen Trick um dieses kurze Aufblitzen der LED zu
umgehen?
Für die PWM benutze ich das PCA in 16bit-PWM-Betrieb.
Danke schonmal für eure Hilfe!
Ein µC kann mit der PWM komplett an 0% und 100% rangehen. Kommt dann
halt Gleichstrom raus. Bestimmt hast Du in deinem Programm irgendwo
einen Überlauf, sodass Du deine PWM versehentlich auf 100% fährst. Ohne
Programm und Schaltplan können wir aber nur raten.
Gruß
Jonathan
Jonathan Strobl schrieb:> Kommt dann> halt Gleichstrom raus
So eine PWM erzeugt immer Gleichspannung, die Polarität ändert sich ja
nicht.
David schrieb:> Ich schätze der µC hat einfach Probleme, eine PWM mit Duty-Cycle nahe 0%> zu liefern?
Wenn dann hat dein Code ein Problem damit :)
Duty-Cycle 0 heißt für den Controller einfach PINx=0, für den µC ist das
das kleinste Problem.
> Gibt es einen Trick um dieses kurze Aufblitzen der LED zu> umgehen?
Wie Jonathan sagt: Mehr Infos rausrücken xD
David schrieb:> Gibt es einen Trick um dieses kurze Aufblitzen der LED zu> umgehen?
PWM abschalten.
Ich denke mal, das funktioniert wie bei einem AVR: beim Hochzählen bis
zum maximalen Wert ist der Ausgang 0 - Beim Erreichen umschalten auf 1 -
jetzt weiterzählen bis zum eingestellten 'PWM-Wert' - wieder
ausschalten. Und das dauert eben von 'Max' bis '0' einen Timertakt.
Danke euch schonmal!
Kompletten Code hier jetzt reinposten wäre denk ich übertrieben...
Also das ganze funktioniert so:
Das PCA zählt permanent von 0x0000 bis 0xffff hoch (mit 3MHz), dazu gebe
ich im Programm einen Compare-Wert vor, am Anfang soll dieser 0 sein.
Sobald der Counter über diesen Wert läuft schaltet der Port auf high,
LED ist dann aus.
Dachte auch erst ich hab nen Fehler in der Zählschleife drin (dass ich
den Compare-Wert öfter verringere als ich ihn vorher erhöht habe).
Allerdings hab ichs in Einzelschritt durchprobiert und komme da immer
wieder bei 0 raus, dann beginnt die Zählschleife von vorne. Das störende
Aufblinken ist auch ab einem Compare-Startwert von ~0x40 nicht mehr da,
ich erhöhe Compare aber bei jedem PCA-Interrupt um 0xfa, kann also nicht
einen ganzen Schritt zu viel runterzählen...
Hoffe das war einigermaßen verständlich was ich meine, fällt mir
bisschen schwer das in Worte zu fassen ;)
Dominik S. schrieb:> So eine PWM erzeugt immer Gleichspannung, die Polarität ändert sich ja> nicht.
Doch: Das ist eine Wechselspannung, die mit einer Gleichspannung
überlagert ist. Wenn Du auf 12V Welchselspannung 20V Gleichspannung
drauflegst, ändert sich die Polarität ja auch nicht mehr, aber die
Wechselspannung ist trotzdem noch vorhanden. Wenn Du vom PWM-Signal den
Gleichanteil wegfilterst, bleibt auch nur noch die Wechselspannung
übrig.
Aber ich glaube, das wird jetzt ein Bisschen Off-Topic und ist auch eine
Definitionsfrage ;)
David schrieb:> Kompletten Code hier jetzt reinposten wäre denk ich übertrieben...
Nein, ohne Quellcode vor der Nase kann man keine Fehler finden. Zeig
schon her ;)
Gruß
Jonathan
Dominik S. schrieb:> So eine PWM erzeugt immer Gleichspannung, die Polarität ändert sich ja> nicht.
Da würde dich eine FFT eines belehren. Eine Gleichspannung hat nur einen
Beitrag bei 0 Hz, d.h. sie ändert sich zeitlich nicht.
> Hoffe es ist nachzuvollziehen wie das funktionieren soll
Wenn man wissen würde welchen SiLabs 8051 Du denn verwendest, wäre es
einfacher. Ich tippe mal auf 8051F020 o.ä.
Jim Meba schrieb:>> Hoffe es ist nachzuvollziehen wie das funktionieren soll>> Wenn man wissen würde welchen SiLabs 8051 Du denn verwendest, wäre es> einfacher. Ich tippe mal auf 8051F020 o.ä.
Sorry, wusste nicht dass das wichtig ist...Ist ein 8051F340...
Gruß David
Hi
>;---------------------------------------------------------------------- -->;Interrupt-Vektoren>;---------------------------------------------------------------------- -->ORG 05Bh ;PCA Interrupt-Adresse>clr CF ;Interrupt-Flag rücksetzen>call PCAINT ;springe in Interrupt-Serviceroutine
An dieser Stelle sollte ein Sprung zur ISR stehen. Oder ist das beim
8051 anders.
MfG Spess
David schrieb:> Sorry, wusste nicht dass das wichtig ist...Ist ein 8051F340...
Naja, es gibt ja nur über 500 Typen des 8051 von etwa 50 Herstellern.
Das die alle irgendwelche Unterschiede haben, sollte klar sein.
Auch muß man ja zu Anfang das entsprechende Include reinschreiben, damit
der Assembler/Compiler überhaupt die richtigen Adressen findet.
Geht daraus nicht eindeutig das verwendete Target hervor, schreibt man
es als Kommentar mit rein.
In die Vektortabelle schreibt man immer nur den Sprung zur
Behandlungsroutine rein, keinen sonstigen Code!
Dein Sprung zum Main kollidiert mit dem ersten Interruptvektor.
Vielleicht willst Du ihn später mal verwenden und dann krachts.
Peter
Hallo!
Ohne jetzt den Code komplett analysiert zu haben fällt auf den ersten
Blick dieses auf:
> call PCAINT ;springe in Interrupt-Serviceroutine
Das ist kein Sprung, sondern ein Unterprogrammaufruf. Wenn jetzt in der
Service-Routine das RETI kommt, was macht dann der Controller?
Route 66 schrieb:>> call PCAINT ;springe in Interrupt-Serviceroutine> Das ist kein Sprung, sondern ein Unterprogrammaufruf. Wenn jetzt in der> Service-Routine das RETI kommt, was macht dann der Controller?
Ich bin davon ausgegangen er springt wieder dahin im Programm wo er war,
als der Interrupt aufgetreten ist...was ist daran falsch?
Hi
>Ich bin davon ausgegangen er springt wieder dahin im Programm wo er war,>als der Interrupt aufgetreten ist...was ist daran falsch?
Normalerweise ja. Wenn ein Interrupt auftritt wird die aktuelle Adresse
auf den Stack gelegt und der Sprung zur ISR, der an der zum Interrupt
gehörenden Stelle in der Interrupttabelle steht, ausgeführt. Bei dir
steht aber dort kein Sprung, sondern ein Call. Und bei einem Call wird
automatisch die Adresse des Befehls nach dem Call automatisch auf den
Stack gelegt. Beim RETI der ISR wird dann die Rückkehradresse vom Stack
geholt. Dank deinem Call ist das aber nicht die Adresse an der Stelle
des Interrupts sondern die nach 'call PCAINT'. Und damit geht es bei
dem, was dort zufällig steht weiter.
MfG Spess
spess53 schrieb:> Hi>>>Ich bin davon ausgegangen er springt wieder dahin im Programm wo er war,>>als der Interrupt aufgetreten ist...was ist daran falsch?>> Normalerweise ja. Wenn ein Interrupt auftritt wird die aktuelle Adresse> auf den Stack gelegt und der Sprung zur ISR, der an der zum Interrupt> gehörenden Stelle in der Interrupttabelle steht, ausgeführt. Bei dir> steht aber dort kein Sprung, sondern ein Call. Und bei einem Call wird> automatisch die Adresse des Befehls nach dem Call automatisch auf den> Stack gelegt. Beim RETI der ISR wird dann die Rückkehradresse vom Stack> geholt. Dank deinem Call ist das aber nicht die Adresse an der Stelle> des Interrupts sondern die nach 'call PCAINT'. Und damit geht es bei> dem, was dort zufällig steht weiter.>> MfG Spess
Danke, jetzt hab ich das Problem erkannt...d.h. ich müsste entweder das
"call" durch ein "jmp" ersetzen, oder das reti in die Zeile unterhalb
von "call PCAINT" schreiben, richtig?
So im Nachhinein wundert es mich aber, dass das Programm überhaupt
funktioniert - er müsste doch jetzt wenn er nach dem call wieder
zurückspringt wieder weitergehen im Code, also wieder zu "Init:" und den
darauf folgenden Befehlen oder?
LG David