Servus,
der Link des Artikels ist hier:
[http://www.mikrocontroller.net/articles/Soft-PWM].
Ich habe einige Fragen zum zweiten Versuch im Artikel.
1. Handelt es sich um den Normal-Mode oder den CTC-Modus? Nach der Zeile
1
TCCR1B=1;
sollte das Normal-Mode sein, aber im Normal-Mode spielt das 'OCR1A'
keine Rolle!
2.
1
OCR1A+=(uint16_t)T_PWM;
Was macht diese Zeile in der ISR ? Nach jeder ISR wird das OCR1A um 312
(T_PWM) erhöht, also 0, 312, 624 usw. Das bedeutet, die Zeitabstände
zweier ISRs sind immer höher: 312, 624 usw. Habe ich falsch verstanden?
Irgendwann muss das OCR1A einen Überlauf bekommen, und dann?
3.
1
TCCR1B=1;// Timer läuft mit vollem Systemtakt
2
TIMSK|=(1<<OCIE1A);// Interrupt freischalten
Geht es um Kanal A oder Kanal B? Sollte TIMSK eigentlich TIMSK1 heissen?
Vielen Dank für jeden Hinweis.
Senmeis
Owen Senmeis wrote:
> aber im Normal-Mode spielt das 'OCR1A'> keine Rolle!
Doch das tut es.
Der Output Compare Interrupt wird ausgelöst, wenn der Timerstand mit dem
OCR1A Register übereinstimmt.
Der Timer läuft halt weiter ohnr das sonst irgendwas passiert. Aber rein
durch die Übereinstimmung der beiden Register wird der Interrupt
ausgelöst. Alles andere ergibt sich dann daraus
> Irgendwann muss das OCR1A einen Überlauf bekommen, und dann?
dann gibts einen Überlauf, und es geht wieder von vorne los.
Macht aber nichts. Den das Zählregister hat ja genau den gleichen
Überlauf.
Zitat ueber den normalen Modus aus dem Handbuch:"The Output Compare
units can be used to generate interrupts at some given time. Using the
Output Compare to generate waveforms in Normal mode is not recommended,
since this will occupy too much of the CPU time.". Aber an welchen
Zeitpunkten?
Zu meiner zweiten Frage: Nach meinem Verstaendnis sollen die Zeitspannen
zweier Aufrufe der ISR immer gleich sein, z.B.
alle 50us, nicht wahr?
Gruss
Senmeis
Ich grabe mal das alte Thema aus, da ich genau die gleiche Frage zu dem
Artikel habe. Eine Antwort habe ich im Forum noch nicht gefunden.
Also was genau die Zeile:
OCR1A += (uint16_t)T_PWM;
macht. Ich bin bis jetzt auch immer davon ausgegangen, dass der ISR
immer gleich lang sein sollte. In vielen anderen Beispielen hier im
Forum ist das auch so.
Wer kann da weiter helfen?
Gruß,
Joachim
@oachim (Gast)
>Also was genau die Zeile:>OCR1A += (uint16_t)T_PWM;
Ganz einfach, damit wird der Zeitpunkt für den nächsten Interrupt
festgelegt. Zum aktuellen Wert von OCR1A wird der Wert T_PWM addiert.
>macht. Ich bin bis jetzt auch immer davon ausgegangen, dass der ISR>immer gleich lang sein sollte.
Das hat mit der LÄNGE der ISR nichts zu tun, sondern mit dem zeitlichen
Abstand des Aufrufs.
> In vielen anderen Beispielen hier im Forum ist das auch so.
Wahrscheinlich weil man sowas des öfteren braucht.
MFG
Falk
Joachim schrieb:> Ich grabe mal das alte Thema aus, da ich genau die gleiche Frage zu dem> Artikel habe. Eine Antwort habe ich im Forum noch nicht gefunden.> Also was genau die Zeile:>> OCR1A += (uint16_t)T_PWM;>> macht. Ich bin bis jetzt auch immer davon ausgegangen, dass der ISR> immer gleich lang sein sollte.
Das hat damit nichts zu tun
Jetzt ist es 12:04
Wenn du in genau 20 Minuten das Licht aufdrehen sollst, dann ist das um
12:04 + 00:20 -> 12:24
Also stellst du deinen Wecker auf 12:24
Der klingelt auch um die Zeit (die ISR kommt)
13 Minuten später sollst das Licht wieder ausschalten. Das wird dann
sein um
12:24 + 00:13 -> 12:37
Also wird der Wecker (wenn er um 12:24 geklingelt hat) auf die neue
Weckzeit 12:37 eingestellt. Wenn er klingelt, schaltest du das Licht
wieder aus und rechnest dir anhand des nächsten Zeitintervalls aus, wenn
das Wecker das nächste mal, für die nächste Aktion, klingeln soll.
Und so geht das immer weiter.
Das Uhrwerk im Wecker ist dein Timer.
Die Einstellung der Klingelzeit ist das OCR Register
Und das Klingeln ist der Aufruf der ISR
Jetzt klarer?
Danke schon mal für die Antworten!
Da habe ich mich etwas ungeschickt ausgedrückt. Ich wollte auch sagen,
dass sich die Zeit zwischen den ISRs unterscheidet, also nach jeden ISR
wird die Pause länger, bis die 16 bit voll sind und es wieder von vorne
losgeht.
Ich glaube ich habe es jetzt verstanden. Ich habe immer ein festes
Zeitintervall (die T_PWM) bei dem ich schaue ob ich die LEDs (oder
Lampen ;-) ) entweder an oder aus schalten muss.
Hat diese Vorgehensweise einen Vorteil gegenüber einer festen Frequenz
der ISR?
Gruß,
Joachim
@Joachim (Gast)
>Ich glaube ich habe es jetzt verstanden.
Ich glaube nein.
> Ich habe immer ein festes>Zeitintervall (die T_PWM) bei dem ich schaue ob ich die LEDs (oder>Lampen ;-) ) entweder an oder aus schalten muss.
In deinem Beispiel ja.
>Hat diese Vorgehensweise einen Vorteil gegenüber einer festen Frequenz>der ISR?
Welche Vorgehensweise? Dein Beispiel hat eine feste ISR-Frequenz. Aber
das dritte Beispiel im Artikel Soft-PWM hat KEINE feste Frequenz.
Der Grund und Vorteil steht im Artikel.
MFG
Falk
... schrieb:> Solange T_PWM konstant ist, hast Du eine feste Interruptfrequenz.
Nein, weil bei jedem Interrupt OCR1A um T_PWM erhöht wird und somit der
Interrupt später kommt. Oder nicht?
Im Artikel steht da jetzt aber "Im Interrupt, welcher regelmäßig
aufgerufen wird,...." Seh ich allerdings nicht?
Ich vergleiche hier den "zweiten Lösungsansatz" und die "übliche"
Vorgehensweise hier im Forum bei der ein fester Wert für den Compare
Match oder ein Overflow verwendet, eine Variable hochgezählt wird und
abhängig vom Wert der Variable die LEDs gesetzt werden.
T_PWM gibt den "Abstand" zwischen 2 Interrups an. Und wenn der konstant
ist, ist auch die Frequenz konstant. Ist doch nu wirklich nicht soooo
schwer.
Ist im Endeffekt dasselbe, als wenn man den CTC-Mode mit demselben Wert
benutzt.
Bei dem verlinkten Artikel geht es aber um eine Soft-PWM mit acht
Kanälen. Und wenn man den dann auch noch komplett liest und den
Abschnitt "Intelligenter Lösungsansatz" auch noch versteht, dann kann
man eventuell nachvollziehen warum das in diesem Fall genau so gemacht
wird.
Joachim schrieb:> ... schrieb:>> Solange T_PWM konstant ist, hast Du eine feste Interruptfrequenz.>> Nein, weil bei jedem Interrupt OCR1A um T_PWM erhöht wird und somit der> Interrupt später kommt. Oder nicht?
Nein.
Du hast es immer noch nicht.
Der Timer läuft weiter!
Der wird nicht auf 0 gesetzt. Genausowenig wie du deinen Wecker bei
jedem Klingeln nicht auf Mitternacht zurückstellst.
> Im Artikel steht da jetzt aber "Im Interrupt, welcher regelmäßig> aufgerufen wird,...." Seh ich allerdings nicht?
Weil du davon ausgehst, dass der Timer bei jedem Interrupt wieder bei 0
anfängt, aber das tut er nicht. Der zählt einfach weiter.
Jetzt hab ichs aber :-)
Anfangswerte: OCR1A=0 und TCNT1=0
--> 1. Interrupt
nach dem 1. Interrupt: OCR1A=312 und TCNT1=0
--> 2. Interrupt bei OCR1A=312 und TCNT1=312
nach dem 2. Interrupt: OCR1A=624 und TCNT1=312
usw.
==>Fester Abstand zwischen den Interrupts 312 Zyklen :-)
Ihr habt ja recht! Ich bin fälschlicher Weise tatsächlich von einem
"Clear Timer on Compare" ausgegangen.
Da ist der Groschen aber in Pfenningen gefallen (Irgendwo hab ich noch
welche ;-) )
Vielen Dank für eure Mühe!
Joachim
Joachim schrieb:> Anfangswerte: OCR1A=0 und TCNT1=0> --> 1. Interrupt> nach dem 1. Interrupt: OCR1A=312 und TCNT1=0> --> 2. Interrupt bei OCR1A=312 und TCNT1=312> nach dem 2. Interrupt: OCR1A=624 und TCNT1=312
Eigentlich nicht. Es fehlt das setzen von OCR1A und die genaue Notation
des Zeitpunkts. Der Interrupt tritt immer dann auf wenn OCR1A == TCNT1
Also vielmehr so:
Anfangswerte: OCR1A=312 und TCNT1=0
1. Interrupt tritt auf mit OCR1A=312 und TCNT1=312
OCR1A <- 624
2. Interrupt tritt auf mit OCR1A=624 und TCNT1=624
OCR1A <- 936
3. Interrupt tritt auf mit OCR1A=936 und TCNT1=936