Forum: Mikrocontroller und Digitale Elektronik Fehler bei ATMega32 Fast-PWM Frequenz


von Dirk Schlage (Gast)


Lesenswert?

Hallo, Ich habe versucht eine Fast-PWM auf einem ATmega16 bzw. 32 
versucht.
Das Ziel ist erstmal den Pin PD7 mit 38 kHz und 50% Dutycyle wackeln zu 
lassen.

Hier erst mal der verwendete Code:
1
...
2
ISR(TIMER2_OVF_vect)
3
{
4
5
    TCNT2 = 61;     // Nachladen
6
}
7
8
...
9
10
    PORTD = 0;
11
12
    DDRD |= (1 << 7);
13
    TCCR2 = (1 << WGM21) | (1 << WGM20) | (1 << COM21) | (0 << COM20) | (1 << CS20);
14
    TCNT2 = 61;
15
    OCR2 = 158;
16
    TIMSK |= (1 << TOIE2);
17
    sei();
18
...
19
20
21
    for(;;)
22
    {
23
    }
24
...

Über WGM21 und WGM20 wird Mode 3 (Fast PWM) aktiviert.
COM21 ist gesetzt:
  Clear OC2 on compare match, set OC2 at BOTTOM,(non-inverting mode)
CS20 ist gesetzt:
  clkT2S/(No prescaling)
Meine Quarzfrequenz ist 7372800Hz.
7372800 / 38000 = 194,...
255 - 194 = 61
Deshalb lade ich TCNT2 mit 61 und bei jedem Überlauf wird es erneut mit 
diesem Wert geladen.
Ich messe aber ca. 34.5kHz statt 38kHz.
Wenn ich auf internen RC-Osc. mit 8MHz umschalte messe ich etwa 36.5kHz.
(Zumindest sehe ich daran, dass der externe Quarz auch verwendet wird. 
Die Frequenz ist auch ok.)

Weiß jemand wo das Problem liegt.

Danke

von Rainer U. (r-u)


Lesenswert?

Eigentlich brauchst Du weder ISR noch Nachladen..

Ich habe dieses Codebeispiel für Mega328 / das geht analog bestimmt auch 
bei Dir (mit angepassten Rregisternamen, aber dem gleichen CTC Mode):
1
  // set up Timer 2 for IR-LED, 36kHz
2
  TCCR2A = _BV (COM2A0) | _BV(WGM21);  // CTC, toggle OC2A on Compare Match
3
  TCCR2B = _BV (CS20);   // No prescaler
4
  OCR2A =  221;          // compare A register value (222 * clock speed)

von Gernot (Gast)


Lesenswert?

Dirk Schlage schrieb:
> Weiß jemand wo das Problem liegt.

Mal versuchen:

Für den Overflow Interrupt werden Taktzyklen für Einsprung in die ISR 
und Setzen des TCNT verbraten. In der Zeit ist der Timer von 255 auf 0 
und bis TCNT = X gelaufen, bis er dann von der ISR 61 gesetzt wird. Die 
Zeit, in der OC2 auf high ist, ist X + die Zeit von 61 bis 158. Ist also 
auch nicht 50% duty.

von Dirk Schlage (Gast)


Lesenswert?

Hallo und danke für die Antworten.

@Rainer Unsinn:
Stimmt, da kriege ich dann allerdings nur die halbe Frequenz, weil mein 
Port 194 Cycles aus ist und dann 194 Cyles an, usw.
Da ich allerdings im nächsten Schritt auch den Duty-Cyle ändern will, 
ist das mit der CTC nicht so einfach.

@Gernot:
Danke für die Erklärung. Da hätte ich auch drau kommen können. Bei Top 
wird die ISR aufgerufen und etliche Cycles vergehen, bis ich dann 
schließlich den Zähler wieder auf den Startwert gesetzt habe und diese 
Cycles addieren sich schließlich zu meinen 194 Cycles.

Ich denke, ich werde dann mal bei den Modi von Timer1 schauen.

Dirk

von S. Landolt (Gast)


Lesenswert?

Wenn es wirklich dieser Controller mit diesem Timer sein muss, könnte 
man etwas in dieser Art versuchen:
1
ISR(TIMER2_OVF_vect)
2
{
3
//    TCNT2 = 61;     // Nachladen
4
      TCNT2 = 61+TCNT2  +10;
5
}

(aber schön ist es nicht)

von Dirk Schlage (Gast)


Lesenswert?

Danke,

Ich habe es jetzt mit dem Timer1 gemacht:
1
    DDRD |= (1 << 5);
2
    ICR1 = 97L;
3
    TCCR1A = ((1 << COM1A1) | (1 << COM1A0) | (1 << WGM11));
4
    TCCR1B = ((1 << CS10) | (1 << WGM13));
5
    OCR1A = uchOCR;

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.