Moin liebes Forum,
ich habe mal wieder ein Problem und ich habe schon Stunden mit googlen,
lesen und testen verbracht - erfolglos.
Eigentlich ganz einfach: ich verwende auf meinem Stk500 einen ATtiny45 @
8MHz (intern, kein Teiler) und würde gerne aufgrund des 4-Bit-Prescale
mit 16.384 den Timer 1 nutzen. Dazu folgendes Test-Programm im AVR
Studio 7 zusammengeschrieben:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
volatileinti=0;
5
6
ISR(TIMER1_OVF_vect)
7
{
8
i++;
9
PORTB&=~(1<<PB0);// led0 on if ISR is called
10
}
11
12
intmain(void)
13
{
14
DDRB=0xFF;// use B as output
15
PORTB=0xFF;// because leds on stk500 are inverted -> turn all off
// test if timer1 is running -> led1 starts blinking
24
if(TCNT1==0){
25
PORTB|=(1<<PB2);// led2 off at start (==end) of each cycle
26
}elseif(TCNT1==127){
27
PORTB&=~(1<<PB2);// led2 on at mid of each cycle
28
}
29
}
30
}
Was soll ich sagen: PB2 blinkt munter vor sich hin (Timer1 scheint also
zu laufen), PB0 bleibt dauerhaft dunkel (die ISR scheint also nie
angesprochen zu werden). Alle LEDs sind heile (sind die auf dem Stk500)
und es ist nichts weiter angeschlossen.
Fuses (ext, high, low):
0xFF, 0xDF, 0xE2
Ich bin bei meiner Recherche häufiger auf Probleme mit Timer1 beim
ATtiny45 gestoßen, auch hier im Forum, eine Lösung habe ich jedoch nicht
gefunden. Z.B.:
Beitrag "ATTiny45 Timer und Interrupt"Beitrag "Attiny45, timer tut nichts?"
Das bringt mich aber nicht weiter.
Kann mir irgendwer von euch weiterhelfen? Ich bin mit meinem Latein am
Ende. Vielleicht bin ich auch einfach nur zu blind, aber ich sehe im
Datenblatt auch keine weitere Info...
Dank & Gruß,
Ben
Hi,
Vielleicht mal mit toggeln des Pins im IRQ versuchen:
(Es weiss ja niemand wie Deine LED angeschlossen ist)
ISR (TIMER1_OVF_vect)
{
i++;
PORTB ^= (1 << PB0); // led0 on if ISR is called
}
oder (bei neueren AVRs)
ISR (TIMER1_OVF_vect)
{
i++;
PINB &= (1 << PB0); // led0 on if ISR is called
}
Gruß
Andreas
Andreas B. schrieb:> oder (bei neueren AVRs)>> ISR (TIMER1_OVF_vect)> {> i++;> PINB &= (1 << PB0); // led0 on if ISR is called> }
Bei neueren AVRs?! So hab ich das noch nie gesehen. Woher hast du das?
aus der Bibel (Datenblatt) ;-)
z.B. 10.2.2
Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datashee
t.pdf
sorry, muß auch
PINB |= (1 << PB0); // led0 on if ISR is called
heißen
Andreas B. schrieb:> Vielleicht mal mit toggeln des Pins im IRQ versuchen:> (Es weiss ja niemand wie Deine LED angeschlossen ist)
Wie gesagt, das ist die LED vom Stk500, die sind einfach nur invertiert
angeschlossen. Habe trotzdem mal das toggle mit eingebaut und es ändert
sich nichts...
Fluppi schrieb:> Fehlt für Interrupts nicht noch das "sei()" um Interrupts zu aktivieren?
Unglaublich, das war es... Kopf->Tisch, Kopf->Tisch, Kopf->Tisch
Ich bin mir so sicher im Forum gelesen zu haben, die sein automatisch
an... Muss die Stelle nochmal suchen. (Um ehrlich zu sein dachte ich mir
schon "*seufz*, der Kommentar wird mir nicht weiterhelfen"... Riesen
Irrtum meinerseits :-) Nur gut das ich es trotzdem probiert habe!)
Super vielen Dank!
Ben
Andreas B. schrieb:> PINB &= (1 << PB0); // led0 on if ISR is called
Nur am Rande: dann gehen alle anderen PBx von HIGH auf LOW (und damit
die LED an) ;-) Habe es ausprobiert und es erscheint mir auch logisch...
Toggeln kann man meines Erachtens so nicht...
Grüße,
Ben
Eine Frage habe ich leider noch. Das Datenblatt besagt zum TCCR1:
> TCCR1 – Timer/Counter1 Control Register> - Bit 7 – CTC1 : Clear Timer/Counter on Compare Match> When the CTC1 control bit is set (one), Timer/Counter1 is reset to $00 in> the CPU clock cycle after a compare match with OCR1C register value. If the> control bit is cleared, Timer/Counter1 continues counting and is unaffected> by a compare match.
Es wird hier eindeutig vom OCR1C gesprochen, es gibt aber nur
Compare-ISRs für OCR1A und *OCR1B*:
1
TIMER1_COMPA_vect
und
1
TIMER1_COMPB_vect
(laut AVR Studio 7)
Zudem ist im TIMSK nur OCIE1A und OCIE1B für Compare-Interrups
vorhanden, ansonsten nur der TOIE1 für den Overflow-Interrupt. Genau
so wie im TIFR nur die Compare-Flags OCF1A und OCF1B, sowie TOV1
als Overflow-Flag sind.
Das klingt für mich schizophren... Ich kann C nutzen um z.B. nur bis 127
zu zählen, der Zähler wird zurück gesetzt, einen Interrupt kriege ich
dafür aber nicht?!?
Muss ich zusätzlich dann noch A oder B nutzen um (ebenfalls auf 127)
einen compare auszuführen?
BTW: ich nutze keine PWM, ich brauchen den Timer nur in Software,
nicht an einem Außgang.
Ben B. schrieb:> Das klingt für mich schizophren... Ich kann C nutzen um z.B. nur bis 127> zu zählen, der Zähler wird zurück gesetzt, einen Interrupt kriege ich> dafür aber nicht?!?
Sieht für mich im Datenblatt auch so aus.
> Muss ich zusätzlich dann noch A oder B nutzen um (ebenfalls auf 127)> einen compare auszuführen?
Ja, zB OCR1A setzen und den entsprechenden Interrupt nutzen. Overflow
Interrupt wird wohl im Nicht-PWM Mode nicht ausgelöst, wenn der TCNT1
nicht bis 0xFF läuft
>> BTW: ich nutze keine PWM, ich brauchen den Timer nur in Software,> nicht an einem Außgang.
PWM kannst du ja trotzdem einschalten. Schadet doch nichts? Brauchst ja
nicht auf die Pins durchzuschalten. Dann sollte der Overflow Interrupt
bei Erreichen von OCR1C auch kleiner 0xFF ausgelöst werden.
Eindeutig konnte ich das Verhalten im CTC Mode nicht herauslesen. Könnte
man mal ausprobieren.
Versteh dein Problem nicht...
Wenn du beim Compare den Timer zurück setzt, dann ist doch der Compare
Interrupt dein Overflow Interrupt.
Ansonsten kannst du mit dem C Register einfach deinem Overflowwert des
Timer 1 einstellen...
H.Joachim S. schrieb:> TOV1?
Aus der Doku:
> TIFR – Timer/Counter Interrupt Flag Register> - Bit 2 – TOV1: Timer/Counter1 Overflow Flag> In normal mode (PWM1A=0 and PWM1B=0) the bit TOV1 is set (one) when an> overflow occurs in Timer/Counter1.> The bit TOV1 is cleared by hardware when executing the corresponding> interrupt handling vector. Alternatively, TOV1 is cleared, after> synchronization clock cycle, by writing a logical one to the flag.> In PWM mode (either PWM1A=1 or PWM1B=1) the bit TOV1 is set (one) when> compare match occurs between Timer/Counter1 and data value in OCR1C - Output> Compare Register 1C.> When the SREG I-bit, and TOIE1 (Timer/Counter1 Overflow Interrupt Enable),> and TOV1 are set (one), the Timer/Counter1 Overflow interrupt is executed.
Basti schrieb:> Wenn du beim Compare den Timer zurück setzt, dann ist doch der Compare> Interrupt dein Overflow Interrupt.> Ansonsten kannst du mit dem C Register einfach deinem Overflowwert des> Timer 1 einstellen...
Es geht ja gar nicht um das zurücksetzen - es wird bei OCR1C einfach
kein Interrupt ausgelöst, habe ich den Eindruck.
Es gibt für OCR1C keinen Compare-Interrupt und wenn ich OCR1C setze
und dazu noch CTC1 in TCCR1 setze, dann zählt er zwar nur noch bis
OCR1C, löst aber keinen Overflow-Interrupt mehr aus.
Lasse ich CTC1 auf 0, dann wird der Overflow-Interrupt wieder
ausgeführt, aber eben erst beim Wechsel von 0xFF zu 0x00. OCR1C wird
dabei völlig ignoriert.
Viele Grüße,
Ben
Datenblatt 12.3.8 TIFR – Timer/Counter Interrupt Flag Register
In PWM mode (either PWM1A=1 or PWM1B=1) the bit TOV1 is set (one) when
compare match occurs between Timer/Counter1 and data value in OCR1C -
Output Compare Register 1C.
Ben B. schrieb:> Das klingt für mich schizophren... Ich kann C nutzen um z.B. nur bis 127> zu zählen, der Zähler wird zurück gesetzt, einen Interrupt kriege ich> dafür aber nicht?!?> Muss ich zusätzlich dann noch A oder B nutzen um (ebenfalls auf 127)> einen compare auszuführen?>> BTW: ich nutze keine PWM, ich brauchen den Timer nur in Software,> nicht an einem Außgang.
Wo ist denn eigentlich dein Problem? Wenn du OCR1A/B nicht für
Hardware-PWM brauchst, dann nimm doch OCR1A oder B samt
compare-Interrupt bzw. im CTC-Mode.
S. Landolt schrieb:> Datenblatt 12.3.8 TIFR – Timer/Counter Interrupt Flag Register>> In PWM mode (either PWM1A=1 or PWM1B=1) the bit TOV1 is set (one) when> compare match occurs between Timer/Counter1 and data value in OCR1C -> Output Compare Register 1C.
Oh, das hatte ich nicht gesehen, werde das mal ausprobieren! Danke!
H.Joachim S. schrieb:> Wo ist denn eigentlich dein Problem?
Das Problem eher eine Merkwürdigkeit. Es ist einfach das, dass CTC1
nur mit OCR1C arbeitet, OCR1C jedoch wiederum keinen
Compare-Interrupt bietet und (im Normal Modus) keinen Overflow-Interrupt
triggert.
Eine gangbare Lösung ist z.B. OCR1C und OCR1A (oder B) auf den
gleichen Wert zu setzen, CTC1 im TCCR1 und OCIE1A (oder B) im
TIMSK zu setzen, dann wird TIMER1_COMPA_vect (oder B) ausgelöst.
Einen TIMER1_OVF_vect erhält man trotzdem nicht (natürlich ist TOIE1
in TIMSK gesetzt).
Siehe hier:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
volatileinti=0;
5
6
ISR(TIMER1_OVF_vect)// geht nicht
7
{
8
i++;
9
PORTB^=(1<<PB0);// led0 toggle if ISR is called
10
}
11
12
ISR(TIMER1_COMPA_vect)// geht
13
{
14
i++;
15
PORTB^=(1<<PB1);// led1 toggle if ISR is called
16
}
17
18
intmain(void)
19
{
20
cli();
21
22
DDRB=0xFF;// use B as output
23
PORTB=0xFF;// because leds on stk500 are inverted -> turn all off
Werde nun den Tipp von S. Landolt mit aktivierter PWM testen.
Grundsätzlich finde ich die Ausführungen im Datenblatt in diesem Falle
nicht sooo intuitiv... :-) Und mir ist nicht verständlich, warum Atmel
dem OCR1C nicht auch einen Compare-Interrupt spendiert hat.
Melde mich später zum Thema PWM nochmal ;-)
Dank & Gruß,
Ben
Ben B. schrieb:> S. Landolt schrieb:>> Datenblatt 12.3.8 TIFR – Timer/Counter Interrupt Flag Register>>>> In PWM mode (either PWM1A=1 or PWM1B=1) the bit TOV1 is set (one) when>> compare match occurs between Timer/Counter1 and data value in OCR1C ->> Output Compare Register 1C.>> Oh, das hatte ich nicht gesehen, werde das mal ausprobieren! Danke!
Awesome, das funzt! Habe PWM1A in TCCR1 gesetzt und nun wird
TIMER1_OVF_vect bei OCR1C ausgelöst. Jipiee! Nun habe ich sogar 2
mögliche Lösungen ;-)
Vielen Dank an alle!
Ben
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
volatileinti=0;
5
6
ISR(TIMER1_OVF_vect)
7
{
8
i++;
9
PORTB^=(1<<PB0);// led0 toggle if ISR is called
10
}
11
12
intmain(void)
13
{
14
cli();
15
16
DDRB=0xFF;// use B as output
17
PORTB=0xFF;// because leds on stk500 are inverted -> turn all off
Ben B. schrieb:> Nur gut das ich es trotzdem probiert habe!)
Hoffentlich denkst du dran, wenn die wieder mal nicht funktionieren.
Kann man nämlich auch mal vergessen.^^