atmega32 timer2 benutzen

OP #4176810
Lesenswert?

Hi Forum,

ich würde gern den timer2 vom Atmega32 verwenden. Es soll in die 
Interrupt Routine gesprungen werden, nachdem es ein compare match gibt.


Ich würde gern eine 0.01 sec treffen und habe 16 Mhz.

Folgende Einstellung habe ich:
1
TCNT2 =0 ;
2

3
    OCR2 = 100;
4

5
    ASSR |= (0 << AS2);
6

7
    TCCR2 |= (1<< WGM21) | (0 << COM20) | (5 << CS20);

Die ISR Routine sieht so aus:

1
ISR(TIMER2_COMP_vect)
2
{
3

4
  toggle_yellowLED();
5
  
6
}


Leider toggled die LED nicht.

Ich vermute, dass das was in der ISR steht, nicht korrekt ist. Genau 
weiß ich es jedoch nicht.


Vielen Dank :D
Gast #4176890
Lesenswert?

Eugen Thorben schrieb:
> Ich würde gern eine 0.01 sec treffen und habe 16 Mhz.

Dazu passen deine Einstellungen aber nicht. Du hast CTC Mode (1<<WGM21, 
und WGM20 ist nicht gesetzt) und einen Prescaler von 128 (CS22..20). 
D.h. der Timer rennt mit 125 kHz.

Da OCR2 nun auf 100 steht, wird der Timer alle 100 mal zurückgesetzt und 
ein Interrupt ausgelöst, also bei 1250 Hz. Entspricht 0.0008s.

Das liegt weit unter deinen 0.01s, also musst du den Timer seltener 
zurücksetzen... Da du jetzt weißt, wie du von den Werten zur Frequenz 
kommst, sollte es kein Problem sein, von der richtigen Frequenz (100 Hz) 
zu den nötigen Werten zu kommen.

Wenn noch was klemmt, frag nach.
Gast #4177165
Lesenswert?

Hier mal ein Beispiel.
Auszug aus einer C-Soure von mir. Vielleicht hilft es.
1
#define PRESCALER0      ((1 << CS00) | (1 << CS02))     // CLK/1024
2
#define PRESCALER1    ((1 << CS12)|  (1 << CS10))    // dto.
3
#define PRESCALER2    ((1 << CS20) | (1 << CS21) | (1 << CS22))
4
void Init_Timer(void)
5
{
6
  
7
 /* Init Timer0 - Timer1*/
8
   tick2 = 0;
9

10
   TIMSK  |= (1 << OCIE0)| (1 << OCIE1A) | ( 1 << OCIE2);  // OCIE0 and
11
                              // OCIE1A int
12
                              // OCIE2 int
13
   TCCR0 |= PRESCALER0| (1 << WGM01);  // Prescaler and CTC Mode WGM01 
14
    TCNT0  = 0;         
15
  OCR0 = 4;              // 3,6 => 1 ms
16
// This is the central clock with 1 Hz 
17
  TCCR1B = PRESCALER1 | (1 << WGM12);// Prescaler 1024 and CTC Mode
18
  TCNT1 = 0;                // Set to zero
19
  OCR1A = (F_CPU/1024);        // calculate for 1 second 
20

21
// Timer2 is used to debounce the keys
22
  TCCR2 |= PRESCALER2 | (1 << WGM21); // Prescaler 1024 and CTC Mode
23
  TCNT2 = 0;
24
  OCR2 = (F_CPU/1024)/20;        // 20 ms
25

26
    sei();
27
}
#4177236
Lesenswert?

Wenn du eine konstante Zeitbasis haben willst, ist ein Timer im 
CTC-Modus genau das richtige.

Der Timer muss im CTC-Modus sein
Der Compare-Match-A-Interrupt muss aktiv sein
Der Prescaler und Compare-Registe-A-Register muss richtig eingestellt 
sein
1
 * Sample for Clear Timer on Compare Match (CTC) mode:
2
 *
3
 *   /- Clock                       /- Timer/Counter Compare Match A
4
 *   |                              |
5
 *   V                              V
6
 * 16 MHz / ( 64 * ( 249 + 1 ) ) = 1 kHz = 1 (ms)^-1
7
 *            ^       ^
8
 *            |       |
9
 * Prescaler -/       \- Compare Register A
10
 *
11
 * 16 MHz / (   64 * (  24 + 1 ) ) =  10 kHz = 0.1 (ms)^-1
12
 * 16 MHz / (   64 * ( 249 + 1 ) ) =   1 kHz = 1   (ms)^-1
13
 * 16 MHz / ( 1024 * ( 124 + 1 ) ) = 125  Hz = 8   (ms)^-1

für einen Interrupt alle 0,001 Sekunden (1ms) also:
1
OCR2 = 249;
2
TCCR2 = ((0 << FOC2) | (0 << WGM20) | (0 << COM21) | (0 << COM20) | (1 << WGM21) | (1 << CS22) | (0 << CS21) | (0 << CS20));
3
TIMSK = ((1 << OCIE2) | (0 << TOIE2) | (0 << TICIE1) | (0 << OCIE1A) | (0 << OCIE1B) | (0 << TOIE1) | (0 << OCIE0) | (0 << TOIE0));//Interrupts für Timer 0, 1 und 2

Genau 0,01 Sekunden ist leider nicht möglich, musst du in der ISR immer 
bis 10 Zählen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren