PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer 2



ehenkes
08.06.2007, 22:39
Kann dies bitte mal jemand detailliert erklären, wie es hier durch Setzen der Register TCCR2, OCR2 und TIMSK zu 36 kHz kommt.


/* Timer2, zum Betrieb mit der seriellen Schnittstelle, fuer die IR-Kommunikation auf 36 kHz eingestellt. */
TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20);
OCR2 = 0x91; // duty cycle fuer 36kHz
TIMSK |= (1 << TOIE2); // 36kHz counter

Das gleiche bitte für die Ultraschall-Funktion mit 40 kHz:

// Change Oscillator-frequency of Timer 2
// to 40kHz, no toggling of IO-pin:
TCCR2 = (1 << WGM21) | (1 << CS20);
OCR2 = 100; // 40kHz @8MHz crystal
TIMSK |= (1 << OCIE2); // OCIE2: Timer/Counter2 Output Compare Match Interrupt Enable

ehenkes
09.06.2007, 08:28
Ich versuche es mal selbst. Bitte korrigieren, falls falsch:

36 kHz:
Im Register TCCR2 werden die Bits WGM20, WGM21, COM20, COM21, CS20 auf 1 gesetzt.
Das Register OCR2 wird auf hexadezimal 91 - dezimal 145 - gesetzt.
Im Register TIMSK wird das Bit TOIE2 auf 1 gesetzt.

WGM20 und WGM21 bedeuten Modus "Fast PWM".

Pin OC2 wird durch COM20 und COM21 auf "Compare Match" gesetzt.

CS20 bedeutet "No Prescaling".

OCR2 = x91 = dec145 = b10010001 wird ständig mit TCNT2 verglichen. 36 kHz ergeben sich durch 256 - 145 = 111.

4000000 / (256 - 145) = 36000

TOIE2 in TIMSK gesetzt bedeutet "Interrupt Overflow Enabled"

linux_80
09.06.2007, 11:02
Hallo,

der Asuro läuft aber mit 8MHz, deswegen wird für 72000 ausgerechnet, damits nachher wieder passt, also bis $91 zählen ist nur die halbe Frequenz.

ehenkes
09.06.2007, 12:04
Verstehe ich leider noch nicht komplett. Kann mal jemand, der zu 100% durchblickt, bitte die kompletten Formeln hinschreiben und begründen, die mit f = 8 MHz und OCR2 = 0x91 als Input beginnt und 36 kHz als Output liefert.

robocat
09.06.2007, 13:56
die pwmfrequenz hat ja mit dem dutycycle (also wie lange der pin pro durchlauf auf HIGH bleibt) nichts zu tun. bei fast pwm wird nur hochgezählt bis 0xFF. Also:

f=f(osc)/(prescaler*TOP)=8MHz/(1*256)=31250Hz

schlagt mich wenns net stimmt -.-

EDIT: quatsch. sollen ja 36kHz werden. mom, ich guck nochmal ins datenblatt. sry

linux_80
09.06.2007, 14:01
Die Initialisierung von oben stammt aus der neuen AsuroLib, bei dieser gehört aber dann auch noch der Teil in der ISR dazu, dort wird zum Timer $25 addiert.

In der origianl asuro.c wird der CTC-Modus verwendet, und bei jedem Compare der Pin getogglet.

ehenkes
09.06.2007, 14:18
Du meinst diesen Teil des Sourcecodes?


SIGNAL (SIG_OVERFLOW2)
{
TCNT2 += 0x25; //dezimal 37
count36kHz ++;
if (!count36kHz)
timebase ++;

#ifdef RC5_AVAILABLE
if (enableRC5 && !(count36kHz % 8))
IsrRC5(); // wird alle 222.2us aufgerufen
#endif
}

OK, das ist wichtig, weil TCNT2 ja mit OCR2 vergleichen wird.
Könnte bitte jemand exakt und sequentiell erklären, wie TCNT2 in Bezug auf die Frequenz von 8 MHz zählt, wann und warum diese 37 ($25) addiert werden, wann und wie genau der Vergleich mit OCR2=145 ($91) erfolgt und wie aus diesen Zahlen 36000 Hz entstehen. Ich schaffe es leider noch nicht ganz sicher, würde es aber gerne komplett verstehen. Bitte nur die lib 2.7 beachten.

ehenkes
09.06.2007, 14:24
@robocat:
8000000 / (1*(256 - 145)) = 2*36036

Da spielt die Addition von 37 hinein. Diese Anpassung von 36 kHz auf 72 kHz kapiere ich aber leider noch nicht vollends, stehe da auf dem Schlauch.

robocat
09.06.2007, 14:26
ich gebs auf. sorry für die verwirrung. bin heut wohl noch so im halbschlaf.

gruesse

ehenkes
09.06.2007, 14:42
Jetzt muss Du noch erklären, warum der Wechsel gerade bei 145 erfolgt?
37 -> LO -> 145 -> HI -> 256=37 -> ...

145-37= 108
256-145=111
Das ist doch nicht ganz symmetrisch. Da hätte man doch eher 146 oder 147 für OCR2 genommen.

EDIT: Robocat hat seine Erklärung leider zurück gezogen. Er hatte erklärt, dass beim Overflow der Zähler nicht auf 0, sondern auf 37 gesetzt wird. Bei 145 würde der Ausgang von LO auf HI gesetzt, bei 256 dann wieder von vorne. Das ergibt dann aber mit 8000 kHz / (256-37) = 36,5 kHz und ist vielleicht falsch. Aber wie geht es genau?

Ist offensichtlich schwierig zu kapieren, selbst für Experten. Jetzt will ich es aber ganz genau wissen.

Also meine obige Formel scheint mir immer noch der richtige Weg zu 36 kHz. Jetzt muss nur jemand die genaue Abfolge und die Bedeutung der Addition von 37 beim Overflow des Timers erklären.

ehenkes
09.06.2007, 15:08
Bei der Verwendung der US-Einheit wird ja folgende Version verwendet:


ISR(TIMER2_COMP_vect)
{
//TCNT2 += 0x25;
count36kHz++;
if(!count36kHz) timebase++;
}

/**
* initialises the Ultrasonic module
* this function is automaticly called by Chirp
*/
void InitUltrasonics(void)
{
// Change Oscillator-frequency of Timer 2
// to 40kHz, no toggling of IO-pin:
TCCR2 = (1 << WGM21) | (1 << CS20);
OCR2 = 100; // 40kHz @8MHz crystal
TIMSK |= (1 << OCIE2); // OCIE2: Timer/Counter2 Output Compare Match Interrupt Enable

ADCSRA = (0 << ADEN); // deactivate ADC
ACSR |= (1 << ACIS1); // Comparator Interrupt on Falling Output Edge

ADMUX = 0x03; // connect ADC3-input with comparator
SFIOR |= (1 << ACME); // connect ADC multiplexer to comparator
DDRD &= ~(1 << 6); // use Port D Pin 6 as input (AIN0)
}

Hierbei ergibt sich:
4000 kHz / 100 (OCR2) = 40 kHz (Warum 4 MHz anstelle 8 MHz? Wo spielt der Faktor 2 hinein?)

Das mit den Timern wird nirgends sauber erklärt. Robin Gruber verweist auch nur auf das Datenblatt. Auch im wiki-Artikel Timer gibt es keine klare Erklärung. Teilweise sind sogar Fehler enthalten.

Sternthaler
09.06.2007, 15:23
Vielleicht erhellt das angehängte PrograMM ja das Verständniss.
Mit einem Osca kann man am Oscilator-Pin sehen was beim drücken der Tasten dann rauskommt.
Die Tasten ändern folgendes:
Taste 1: Increment OCR2-Wert um 1
Taste 2: Decrement OCR2-Wert um 1
Taste 3: Increment TCNT2-Offset um 1
Taste 4: Decrement TCNT2-Offset um 1

Taste 6: Eingestellte Werte seriel senden.

Ausserdem ist für Leute-Ohne-Osca eine Excel-Datei dabei, in der man die beiden Werte OCR2 und TCNT2 mal eingeben kann und man dann ein 'Bildchen' zum Taktverlauf bekommt.


P.S.: Ich glaube, dass in allen euren Berechnungen nicht berücksichtigt wurde, dass eine kleine Addition auch Zeit frisst.
Im Exel-Blatt wird das in G2 un G3 berücksichtigt.

ehenkes
09.06.2007, 15:41
Also:

8000 kHz / (256-37+3) = 36,036 kHz

Der Timer zählt also von 37 bis 256, dann benötigt er 3 Rechentakte für +=.

... und Symmetrie:

145-37+3 = 111
256-145 = 111

:) Endlich Klarheit!

Tausend Dank an Sternthaler!

radbruch
09.06.2007, 16:17
Klasse. Ich gebe 10 von 10 Punkten für diesen Thread. Grosses Lob für die Hartnäckigkeit @ ehenkes

btw: ich dachte, die avrs machen alles in einem takt :-k

Sternthaler
09.06.2007, 16:36
@radbruch
Schau mal zum Spaß in's ATmega8.pdf (auf der Asuro-CD)
Im Kapitel 'Instruction Set Summary' ab Seite 284 sind auch Befehle mit 4 Takten zu finden. (Schlimm sind die mit Takteanzahlen von 1 bis 3, je nach frag mich nicht.)
Und wie man ja in diesem Thread sieht, kommt es da manchmal auf die Spalte 'CLOCKS' an. Zum Glück nur extrem selten zu lesen ;-) Hauptsächlich bei Interruptdingen wie hier ja nun mal.

Die Zeile mit dem += wird im Assembler so aufgelößt:
in r24, 0x24 ; 36
lds r25, 0x0061
add r24, r25
out 0x24, r24 ; 36
Warum ich im Excel-Blatt aber nur 3 Takte 'dazumogel' kann ich nicht mehr sagen.
@radbruch
Hier haben wir also doch nur Befehle, die nur einen Takt benötigen.


In version.c der Lib noch zu finden wer da das helle Köpfchen war:


/************************************************** **************************
*
* File Name: asuro.c
* Project : asuro library modified for IR collision detector
*
* Description: modifications made in following functions:
*
* SIGNAL (SIG_OUTPUT_COMPARE2) -> SIGNAL (SIG_OVERFLOW2)
* Gettime() counts now 36kHz
* Init() timer2 modified for adjustable duty cycle
* Batterie() bug fixed
* Sleep() counts now 36kHz
* Msleep() counts now 36kHz
*
* Ver. Date Author Comments
* ------- ---------- -------------- ------------------------------
* beta2 11.06.2005 Waste asuro library
* ------- ---------- -------------- ------------------------------
************************************************** ***************************/


(Ich sehe gerade in meiner Version V01, dass ich am 19.06.2005 (ältestes Dateidatum) angefangen hatte über diese Änderung zu grübeln. Wann ich selber drauf gekommen bin, steht da natürlich nicht.)

radbruch
09.06.2007, 17:11
Schau mal zum Spaß in's ATmega8.pdf
Tja, muss ich wohl. Aus "Bequemlichkeit" habe ich mich bisher davor gedrückt. Aber ohne diese Kenntnisse würde ich wohl auf Dauer von euren LIBs abhängig sein.

ehenkes
09.06.2007, 17:13
Zu dem Thema Takt (clock cycle) liest man im Datenblatt des ATmega8(L):



The interrupt execution response for all the enabled AVR interrupts is four clock cycles minimum. After four clock cycles, the Program Vector address for the actual interrupt handling routine is executed. During this 4-clock cycle period, the Program Counter is pushed onto the Stack. The Vector is normally a jump to the interrupt routine, and this jump takes three clock cycles. If an interrupt occurs during execution of a multi-cycle instruction, this instruction is completed before the interrupt is served. If an interrupt occurs when the MCU is in sleep mode, the interrupt execution response time is increased by four clock cycles. This increase comes in addition to the start-up time from the selected sleep mode. A return from an interrupt handling routine takes four clock cycles. During these four clock cycles, the Program Counter (2 bytes) is popped back from the Stack, the Stack Pointer is incremented by 2, and the I-bit in SREG is set.

Das sollte keine Verzögerung einbauen, aber sicher bin ich mir nicht völlig.



The counting direction is always up (incrementing), and no counter clear is performed. The counter simply overruns when it passes its maximum 8-bit value (MAX = 0xFF) and then restarts from the bottom (0x00). In normal operation the Timer/Counter Overflow Flag (TOV0) will be set in the same timer clock cycle as the TCNT0 becomes zero. The TOV0 Flag in this case behaves like a ninth bit, except that it is only set, not cleared. However, combined with the timer overflow interrupt that automatically clears the TOV0 Flag, the timer resolution can be increased by software. A new counter value can be written anytime.

Hier ist alles klar. Ich grüble, ob nicht exakt bei 0 die 37 addiert wird, sondern erst einige Takte später, da der Prozessor nach dem Overflow in der Routine noch mit einigem anderen beschäftigt ist, siehe:


SIGNAL (SIG_OVERFLOW2)
{
a0: 1f 92 push r1
a2: 0f 92 push r0
a4: 0f b6 in r0, 0x3f ; 63
a6: 0f 92 push r0
a8: 11 24 eor r1, r1
aa: 8f 93 push r24
ac: 9f 93 push r25
ae: af 93 push r26
b0: bf 93 push r27
TCNT2 += 0x25;
b2: 84 b5 in r24, 0x24 ; 36
b4: 8b 5d subi r24, 0xDB ; 219
b6: 84 bd out 0x24, r24 ; 36
count36kHz ++;
b8: 80 91 71 00 lds r24, 0x0071
bc: 8f 5f subi r24, 0xFF ; 255
be: 80 93 71 00 sts 0x0071, r24
if (!count36kHz)
c2: 80 91 71 00 lds r24, 0x0071
c6: 88 23 and r24, r24
c8: 99 f4 brne .+38 ; 0xf0 <__vector_4+0x50>




Die Zeile mit dem += wird im Assembler so aufgelößt:
in r24, 0x24 ; 36
lds r25, 0x0061
add r24, r25
out 0x24, r24 ; 36
Warum ich im Excel-Blatt aber nur 3 Takte 'dazumogel' kann ich nicht mehr sagen.


Zur Anweisung +=

In der temporären Datei xxx.lss findet sich bei mir:

TCNT2 += 0x25;
b2: 84 b5 in r24, 0x24 ; 36
b4: 8b 5d subi r24, 0xDB ; 219
b6: 84 bd out 0x24, r24 ; 36

in (In Port) 1 clock
subi (Subtract Constant from Register) 1 clock
out (Out Port) 1 clock

... macht genau 3 Takte. Perfekt!

ehenkes
09.06.2007, 18:00
Die gleiche tiefgehende Analyse bitte für die erweiterte Ultraschall-Funktion mit 40 kHz:


// Change Oscillator-frequency of Timer 2
// to 40kHz, no toggling of IO-pin:
TCCR2 = (1 << WGM21) | (1 << CS20);
OCR2 = 100; // 40kHz @8MHz crystal
TIMSK |= (1 << OCIE2); // OCIE2: Timer/Counter2 Output Compare Match Interrupt Enable


Hierbei wird ja die Zeile mit dem Addieren von 0x25 gestrichen. Nun verstehe ich endlich warum.



ISR(TIMER2_COMP_vect)
{
//TCNT2 += 0x25; //gestrichen!!!
count36kHz++;
if(!count36kHz) timebase++;
}

Das mit dem count36kHz++ erscheint mir inzwischen völlig unlogisch. Gehört das hier nicht auch weg??? Diese Funktion wird doch alle 100 Takte aufgerufen, also ist count36kHz während der Ultraschallphase ein 80 kHz-Counter. Sehe ich das richtig?

ehenkes
09.06.2007, 18:08
Ich versuche es zunächst selbst. Bitte korrigieren, falls falsch:

40 kHz:
Im Register TCCR2 werden die Bits WGM21 und CS20 auf 1 gesetzt.
Das Register OCR2 wird auf dezimal 100 gesetzt.
Im Register TIMSK wird das Bit OCIE2 auf 1 gesetzt.

WGM21 bedeutet Modus "Clear Timer on Compare Match (CTC)". Top ist dabei OCR2.

CS20 bedeutet "No Prescaling".

OCR2 = dec100 wird ständig mit TCNT2 verglichen.

40 kHz ergeben sich durch:

8000000 / 2 * 100 = 40000 (100 Takte Lo-Signal und 100 Takte Hi-Signal, immer abwechselnd, so ist es im Datenblatt auf S. 89 zu bewundern)

OCIE2 in TIMSK gesetzt bedeutet "Timer/Counter2 Output Compare Match Interrupt Enable"


Anmerkung:
https://www.roboternetz.de/wissen/index.php/Timer/Counter_%28Avr%29#CTC_Modus_.28Clear_Timer_on_Comp are_Match_mode.29
sollte m.E. überarbeitet werden. Die Erklärungen dort bringen zu wenig Klarheit.

HermannSW
09.06.2007, 20:58
Hi,

Zu dem Thema Takt (clock cycle) liest man im Datenblatt des ATmega8(L):
...
Das sollte keine Verzögerung einbauen, aber sicher bin ich mir nicht völlig.

...
Hier ist alles klar. Ich grüble, ob nicht exakt bei 0 die 37 addiert wird, sondern ...hat jemand Zugriff auf ein Oszilloskop und kann mal nachmessen, ob es wirklich gemau 36000Hz sind, oder ein bißchen mehr, oder ein bißchen weniger?
Kenntnis der realen Frequenz erleichtert sicherlich das Finden der richtigen Erklärung ...

[Beim PiccoZ sind es 37.31kHz, nicht gerade eine runde Zahl, und als Receiver ist glaube ich ein 38kHz-Chip drin ...
http://hunz.geekheim.de/?p=49
und in der 5. Antwort dort findet man einen Link, wie jemand mit 'nem Scope den X-Twin RC plane transmitter code geknackt hat (mein Sohn hat sich letzte Woche auch so einen Flieger zugelegt ...:))]

ehenkes
24.06.2007, 10:35
Ich habe mal mit einem Frequenzzähler und einem Oszilloskop gemessen: Ergebnisse an der D10 liegen zwischen 36000 und 36015 Hz. Passt also gut.

HermannSW
25.06.2007, 21:51
Ich habe mal mit einem Frequenzzähler und einem Oszilloskop gemessen:Danke!

Ergebnisse an der D10 liegen zwischen 36000 und 36015 Hz.Das ist aber exakt, nicht so "krumme" Werte wie beim PiccoZ ...

damaltor
26.06.2007, 12:39
sowas lässt sich halt mit einer pwm schön realisieren. allerdings ist das von der theorie her schon recht grenzwertig: im datenblatt wird exakt 36 khz angegeben, ohne speilraum. deshalb reagiert der asuro auch so allergisch darauf wenn am poti nicht 100%ig die richtige stellung gefunden wird.

AsuroNeu
23.07.2009, 09:14
Im dem Lib v2.8rc1 ist OCR2 = 0x91(dezimal 145) . Der OCIE2 bit im TIMSK Register wird aber nicht gesetzt.


Erstens brauchen wir diesen Wert in OCR2 immer noch?

Zweitens für eine 36KHz Frequenz müssen wir doch 219Takte + 3Additions Takte = 222Takte zählen (wie beim Overflow Interuppt Enable). Wir zählen ja hier nur bis 145. Kann mir dass jemand vlt. erklären?

Sternthaler
23.07.2009, 12:41
Hallo AsuroNeu,
auch dir erst einmal ein "Willkommen im Forum".

Ich fange mal mit 'Zweitens' an.
Der Timer zählt immer bis 255.

Wenn der Timer bei dem numerischen Wert 145 angekommen ist passiert nur etwas.
Dann nämlich wird durch die Initialisierung:
TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20)

-- WGM20 und WGM21 setzen den Timer in den "Fast PWM"-Mode
-- COM20 und COM21 setzen im "Fast PWM"-Mode einen 'Output Compare Mode'
==>> auf 'Set OC2 on Compare Match, clear OC2 at TOP

dieser 'Compare Match' ausgelöst.
Verglichen wird der Zählerwert (0 bis 255) mit dem in OCR2 hinterlegten Wert 145.

Somit zählt der Timer zwar natürlich auch bis zu dem numerischen Wert 145, aber er muss dafür nicht 145 mal takten.
Schliesslich wird ja im Interrupt, wenn der numerische Timerwert also gerade von 255 auf 0 geht als erstes diese ominöse 37 auf die 0 addiert.
Somit benötigt die Timerhardware nur 145 - 37 = 108 Takte um auf den numerischen Wert 145 zu kommen.
Jetzt fehlen aber immer noch 3 Zeiteinheiten, um in die Mitte von deinen ausgerechneten 222 Takten zu gelangen.
Diese 3 Zeiteinheiten vergehen aber schon 'von alleine' durch die Addition der 37.
--> Und damit hätten wir nun 108 + 3 = 111 <== die Mitte

Warum ist die Mitte relevant?

In der Mitte wird über die Initialisierung auf:
==>> 'Set OC2 on Compare Match, clear OC2 at TOP

eingestellt,
dass Pin OC2 bei 'Compare Match' (145 in OCR2) gesetzt wird (5 Volt)
dass Pin OC2 bei 'TOP' (numerischer Wert bei 255 angekommen) gelöscht wird (0 Volt)

Und erst wenn beide 'Zählzeiten' abgelaufen sind haben wir eine volle Periode unseres Signals.


Frage 'Erstens' ist damit wohl beantwortet. Ja, brauchen wir noch ;-).

Möglicherweise hilft dir auch dieser Erklärungsversuch (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=364831#364831) etwas weiter. (Schau dort mal bei "Achtung: Es wird nun kompliziert, aber die Initialisierung ist hier das A und O." nach.)

Gruß Sternthaler

AsuroNeu
23.07.2009, 13:10
Vielen Vielen Dank Sternthaler.

Die Erklärung in dem anderen Thread war super. Jetzt verstehe ich auch warum wir nur bis 145 in OCR2 steht. Da die IR-LED mit 'duty cycle 50% bei 36KHz ' arbeiten.

Deswegen brauchen wir auch den OCIE2 bit im TIMSK nicht setzen, da dieser kein ISR ist, sondern für IR-Kommunikation gebarucht wird.

Danke nochmals.