Hallo zusammen,
ich arbeite an einem kleinem Programm, bei dem ich bisher Timer0 und
Timer1 schon in Gebrauch habe. Zeitgleich dazu möchte ich mit Timer2 die
LEDs dimmen und hier stoße ich auf ein Problem...
In Timer0 möchte ich Timer2 immer unterschiedlich vorladen, damit es so
aussieht als würden die LEDs pulsieren. Timer0 wirft ungefähr alle 100ms
einen Overflow...
Timer0 sieht also so aus:
1
fading:
2
; Timer 2 starten
3
cpi runs, 0
4
brne timer2on ; Damit der Timer nur einmal gestartet wird
5
ldi temp, 250
6
out TCNT2, temp
7
ldi temp, 0b010; Vorteiler 1
8
out TCCR2, temp
9
timer2on:
10
out TCNT2, runs
11
12
end:
13
inc runs
14
rjmp exit
In Timer2, der das eigentliche Fading machen soll sieht es so aus:
1
Timer2_Overflow: ; LED-Fading
2
3
push temp ; Sichern von "TEMP" im Stack
4
in temp, SREG ; Einlesen des SREG
5
push temp ; Schreiben von SREG im Stack (KOPIE)
6
7
sbic PORTB, 0 ;Nächsten Befehl überspringen, falls Bit0 abm PortB ist AUS (= LED ist EIN)
8
rjmp led_ein2 ;Ansonsten LED einschalten (s. unten).
9
sbis PORTB,0 ;Überspringen, falls Bit0 abm PortB ist EIN (= LED ist AUS)
10
rjmp led_aus2 ;Ansonsten LED ausschalten (s. unten).
11
12
led_ein2: ;Zum Einschalten:
13
ldi temp, 0x00
14
out PORTB, temp
15
out PORTD, temp
16
rjmp end2 ;und beenden.
17
led_aus2: ;Zum Ausschalten:
18
ldi temp, 0xFF
19
out PORTB, temp
20
out PORTD, temp
21
rjmp end2
22
23
end2:
24
pop temp ; LESEN von SREG vom STACK (KOPIE)
25
out SREG, temp ; Wiederherstellen von SREG
26
pop temp ; Wiederherstellen von "TEMP"
27
reti ; ISR beenden.
Der Vorteiler für TImer2 muss bei 32 bleiben, sonst flackert es
offensichtlich. Allerdings habe ich schon verschiedene Werte zum
vorladen probiert, doch ein richtiges pulsieren ist nicht zu sehen.
Was kann ich da noch ändern, damit ich meinem Ziel näher komme??
Vielen Dank :-)
HI
>Was kann ich da noch ändern, damit ich meinem Ziel näher komme??
Beschäftige dich mit PWM und benutze das OC-REgister. Mit dem unseligen
Vorladen kommst du auf keinen grünen Zweig.
Und das
> sbic PORTB, 0 i> rjmp led_ein2> sbis PORTB,0> rjmp led_aus2> led_ein2:> ldi temp, 0x00> out PORTB, temp> out PORTD, temp> rjmp end2> led_aus2:> ldi temp, 0xFF> out PORTB, temp> out PORTD, temp> rjmp end2
kannst du einfach dadurch
Hi Spess,
danke für die Antwort.
Wenn ich das OCR2-Register benutze, dann muss ich doch vom
Overflow-Interrupt zum CompareMatch-Interrupt wechseln, richtig?
Im Timer-Tutorial steht relativ weniv zu Timer2. Wie genau gehe ich
damit vor? Was genau ist am OCR2 besser als am vorladen des TCNT2?
> kannst du einfach dadurch>> in temp,PortB> com temp> out PortB,temp> out PortD,temp
klar, das hatte ich nur von woanders entnommen. Werde das vereinfachen.
Roland Moch schrieb:> Hi Spess,>> danke für die Antwort.>> Wenn ich das OCR2-Register benutze, dann muss ich doch vom> Overflow-Interrupt zum CompareMatch-Interrupt wechseln, richtig?
Nein, warum?
Der Timer 2 hat genauso einen Overflow Interrupt wie der Timer 0. Wie
alle Timer.
> Im Timer-Tutorial steht relativ weniv zu Timer2. Wie genau gehe ich> damit vor?
Genau gleich. Die Timer sind alle ähnlich. Hast du einen verstanden,
hast du alle (zumindest in den Grundzügen) verstanden. Und die Details,
was der Timer alles kann stehen im Datenblatt des Prozessors.
> Was genau ist am OCR2 besser als am vorladen des TCNT2?
Warum willst du dir Arbeit machen, wenn die Hardware deine LED komplett
ohne dein Zutun ganz von alleine mittels PWM dimmen kann?
Timer richtig konfigurieren und der dimmt deine LED ganz von alleine auf
den Wert den du haben willst. Du musst nur noch die jeweilig gewünschte
Helligkeit ins OCR Register eintragen (und zeitlich variieren). Fertig
> Timer richtig konfigurieren und der dimmt deine LED ganz von alleine auf> den Wert den du haben willst. Du musst nur noch die jeweilig gewünschte> Helligkeit ins OCR Register eintragen (und zeitlich variieren). Fertig
Sorry, wenn ich so blöd frage, aber irgendwie bleiben nach dem Tutorial
auf dieser Seite immer noch Fragen dazu offen... Hast du vielleicht
einen guten Link?
Habe irgendwo gelesen, dass die PWM eine LED an einem bestimmten PIN
dimmen kann, aber in meinem Fall muss ich PORTB und PORTD dimmen. Dann
geht das nicht mit diesem "Automatismus", oder?
EDIT: Also ich werd irgendwie den OCR2 für die Helligkeit einstellen
müssen und laut Datenblatt das WGM21:0 = 1 (was mir nich sonderlich viel
sagt) und dann lüppt die Sache von alleine? Auch an meinen beiden Ports?
Hi
>Sorry, wenn ich so blöd frage, aber irgendwie bleiben nach dem Tutorial>auf dieser Seite immer noch Fragen dazu offen
Das Tutorial ist für den Einsieg gedacht. Aber es kann dich nicht bis an
dein Lebensende begleiten. Nimm dir das Datenblatt und werde flügge.
MfG Spess
Hallo nochmal,
nunja, ich bin immer noch ziemlich blutiger Anfänger...
Habe mir das Datenblatt mal angeschaut und alles relevante zum Timer2
durchgelesen. Also ich würde so vorgehen (Bitte verbessert mich):
1. Im TIMSK die entsprechenden Interrupts "erlauben"
2. LSB von WGM21 auf 1 setzen, um die phasenkorrekte PWM zu benutzen
3. Im OC2 die Helligkeit einstellen, oder eben wie hoch der Timer zählen
soll
4. Über COM21 ist (nicht)invertierte PWM einstellbar
5. Nun wird eine entsprechende Waveform am OC2-Pin (muss auf output
geschaltet sein) generiert
Nun meine Fragen:
1. Ist obiges Vorgehen korrekt?
2. Wird die Waveform am OC2-Pin ohne irgendwelchen Code im
InterruptHandler erzeugt (Vermutung: Ja)?
3. Wie kann ich damit meine Ports pulsweitenmodellieren, was ja mein
eigentliches Ziel ist. Da bringt mir doch auch eine Waveform an OC2
nichts?
Entschuldigt bitte, wenn ich euch nerve, aber da Datenblatt überfordert
mich doch schon ziemlich und alles, was mir wichtig erschien, habe ich
oben zusammengefasst.
Ich wäre wirklich sehr dankbar, wenn sich jemand erbarmen würde, um mir
eine Hilfestellung zu geben, damit ich schneller "flügge" werden kann...
Einen schönen Abend an Alle :-)
Hallo zusammen,
ich habe mir das Datenblatt "reingezogen" und ich habe es hinbekommen
eine PWM an PORTB3 zu etablieren. Das habe ich daran erkannt, dass ich
bei Prescaler 1024 ein deutliches blinken/flackern sehe, dass vergeht,
wenn ich den Prescaler runtersetze.
Der wesentliche Code-Ausschnitt sieht so aus:
1
; Prog4 ausfuehren: Test-Fading
2
ldi temp, 0x01 ; Zur Kontrolle die ersten beiden LEDs einschalten
3
out PORTB, temp
4
out PORTD, temp
5
6
ldi temp, 1<<OCIE2 | 1<<TOIE1 | 1 <<TOIE0 ; Timer0-Overflow und Timer1-Overflow und Timer2-Compare "erlauben"
Allerdings kann ich keine Helligkeitsänderung an der LED an PORTB3
feststellen, egal ob ich OCR2 mit 0xFF oder 0x00 oder irgendetwas
dazwischen lade. Dies dürfte wohl an der logarithmischen
Helligkeitswahrnehmung unseres Auges zu tun haben - oder an einem
Programmfehler...
Oder gibt es da noch einen anderen Trick um eine deutlichere
Helligkeitsänderung herbeizuführen?
Roland Moch schrieb:
> Der wesentliche Code-Ausschnitt sieht so aus:
... das ist nun nicht unbedingt das Wesentliche.
Also, ich würde so rangehen:
PWM-Signal mit Timer1/ 16Bit/ Fast-PWM. Damit hat man 256 sichtbare(!)
Helligkeitsunterschiede (das liegt einmal tatsächlich an der Wahrnehmung
des Auges und außerdem an der Leistungsausbeute bei PWM. Bei einer
Motoransteuerung wäre der Effekt der gleiche.). Die einzelnen Stufen
gehen dann von s=1 .. 256. Mit s^2-1 füttert man später das OC-Register.
Den Maximalwert (volle Helligkeit) schreibt man ins IC-Register (Bei
Benutzung aller 256 Stufen: 0xFFFF). Jetzt braucht man nur noch im
Interrupt von irgend einem anderen Timer entsprechend der gewünschten
Helligkeit eine Variable hoch- und runterzählen lassen und die Werte
eintragen.
Hi,
>>ldi temp, 1 << COM20 | 1 << WGM21 | 0 << CS22 | 1 << CS21 | 0 << CS20> ^^^^^^^^^^>>Du hast CTC und nicht PWM eingestellt.
Wenn ich das richtig verstanden habe, dann muss ich WGM21 auf 0 und
WGM20 auf 1 setzen. Werde das später zu Hause mal austesten...
Angenommen ich setze WGM21 und WGM20 auf 1, dann hätte ich doch eine
FastPWM, aber laut dem Mikrocontroller-Tutorial kann Timer2 doch nur
einen phasenkorrekte PWM. Was ist denn nun richtig und was falsch?
(Zu den anderen Antworten kann ich mich ebenfalls heute Abend mal
melden...)
Aber es ist immernoch kein Helligkeitsunterschied feststellbar, egal ob
ich OCR2 mit 0x00, 0xFF oder 0x99 lade...
Wo ist denn da der Wurm drin???
Ich hab auch mal das komplette Programm hochgeladen, beachtet dabei
bitte das prog so vorgeladen wird, dass immer Prog4 ausgeführt wird...
Stimmt, das ist wirklich nicht erlaubt? Was macht der Microcontroller in
so einem Fall? Stürzt der ab? Macht der irgendetwas unkontrollierbares?
Ich hatte COM20 doch extra auf 1 gesetzt, damit PortB3 bei CompareMatch
getoggled wird. Wie soll ich das denn sonst machen?
Roland Moch schrieb:> Ich hatte COM20 doch extra auf 1 gesetzt, damit PortB3 bei CompareMatch> getoggled wird.
Mit "Toggeln bei Compare-Match" hättest du aber gar keine PWM.
(gar nicht mal so unwahrscheinlich, dass du genau dieses Toggeln bei
Compare-Match jetzt hast)
> Wie soll ich das denn sonst machen?
Ins Datenblatt schauen, und den richtigen COM-Modus raus suchen.
Ok, machen wir mal ein kleines Ausschlussverfahren:
COM21/COM20
0 / 0 - Keine PWM an PortB3 - will ich nicht
0 / 1 - Reserved - geht eh nicht
1 / 0 - Clear OC2 on Compare Match when up-counting. Set OC2 on Compare
Match when downcounting
1 / 1 - Set OC2 on Compare Match when up-counting. Clear OC2 on Compare
Match when downcounting
Zwischen den letzten beiden kann ich mich nicht wirklich entscheiden.
Dürften die nicht dasselbe bezwecken (für meine ganz eifnache
LED-Dimmung) nur genau umgekehrt?
Bin jetzt übers Wochenende zu Hause und kann nichts testen, aber stimmt
meine Annahme? Würde beides gehen ohne bei meinem einfachen Projekt
einen Unterschied zu bewirken?
Schönen Morgen noch an Alle :-)
Hallo Spess,
danke für die Erklärung.
Ich komme leider erst Dienstag wieder an die Hardware dran, dann werde
ich das testen :-)
Bis dahin wünsch ich euch allen frohe Ostern und Ruhe vor mir ;-)
Hi,
kurze Rückmeldung meinerseits:
Es klappt nun alles hervorragend. Habe mich doch noch für eine
Hardware-PWM (Fast-PWM) entschieden und betreibe damit den kompletten
PORTB und PORTD. Im Compare-Interrupt werden die Lichter ausgeschaltet
und im Overflow-Interrupt an.
Der 8-Bit-Timer löst dafür schon fein genug auf - gefällt mir sehr gut
:-)
Danke nochmal für eure Hilfe :-)