pwm atmega16 falsche frequenz

OP #1349508
Lesenswert?

hallo leute, ich versuche grade eine pwm mit dem atmega16 zu erzeugen 
und kriege komischerweise eine frequenz von 15,63khz anstatt wie 
eingestellt 20khz. hat jemand ne idee weshalb das so ist?

#define TIMER_MAX 200

void pwm(void){

TCCR2 = 0b01101001;
TCNT2 = TIMER_MAX;

// FOC | WGM20 | COM21 | COM20 | WGM21 | CS22 | CS21 | CS20
// Fast PWM | non-inverting mode | No prescaling
// f_PWM = f_CLK / N * TCNT2 | f_CLK = 4MHz | N = 1 | TCNT2 = 200 | ==> 
20kHz

OCR2 = (0.50 * TIMER_MAX);
ASSR |= (0<<AS2); // synchronous timer/counter2
}
#1349529
Lesenswert?

Wie kommst du auf die 20kHz?

(Die Zahl ist mir etwas zu glatt. Da musst du einen sehr krumme 
Taktfrequenz haben, damit sich 20kHz einstellen)


1
#define TIMER_MAX 200
2
TCNT2 = TIMER_MAX;
Ähm. Du denkst jetzt aber nicht wirklich, dass du den Zählbereich des 
Timers auf die Art auf 0 bis 200 limitiert hast? Zumindest der Kommentar
1
// f_PWM = f_CLK / N * TCNT2 | f_CLK = 4MHz | N = 1 | TCNT2 = 200 | ==> 20kHz

lässt in mir diesen Verdacht aufkommen.


Edit:
1
TCCR2 = 0b01101001;

Wenn man nur diesen Unsinn ausrotten könnte. Ich brauch fast 2 Minuten 
um durch Vergleich mit dem Datenblatt + Notizzettel zu erkennen, welche 
Bits da gesetzt sind. (Wenn ich im Datenblatt endlich die Tabelle 
erscrollt habe um die gesetzten Bits mit einem Modus in Verbindung zu 
bringen, hab ich schon wieder vergessen, welcher 1-er denn nun welches 
Bit war. Also wieder zurückscrollen und mit der Register-Bit 
Beschreibung vergleichen. Mist, jetzt hab ich die Bits wieder den 
Bitnamen zugeordnet, aber wie war das nochmal in der Tabelle? und schon 
wieder scrollen ....
1
  TCCR2 = ( 1 << WGM20 ) |
2
          ( 1 << WGM21 ) |
3
          ( 1 << COM21 ) |
4
          ( 1 << CS20  );
#1349574
Lesenswert?

Stefan Z. schrieb:
> ahh ok danke, ich dachte die 256 im datenblatt stehen für das TCNT2
> register, welches beliebig beschrieben werden kann. nun ist halt die
> frage wie ich genau 20khz hinbekomme? wahrscheinlich nur mit einem 10bit
> timer

Such dir im Datenblatt den Timer, bei dem du die Obergrenze festlegen 
kannst ( in den PWM Tabellen ist das der TOP Wert )
Gast #1349600
Lesenswert?

Hi

>Such dir im Datenblatt den Timer, bei dem du die Obergrenze festlegen
>kannst ( in den PWM Tabellen, ist das der TOP Wert )

Oder nimm einen passenden Quarz. 5,12MHz (Reichelt) passt genau.

MfG Spess
OP #1349608
Lesenswert?

void pwm(void){
  TCCR1A |= (1<<COM1A1); // fast pwm , non-inverting mode)
  TCCR1A |= (1<<COM1B1); // fast pwm , non-inverting mode)
  TCCR1A |= (0<<COM1A0); // fast pwm , non-inverting mode)
  TCCR1A |= (0<<COM1B0); // fast pwm , non-inverting mode)
  TCCR1A |= (1<<WGM11); // Fast PWM, 10-bit
  TCCR1A |= (1<<WGM10); // Fast PWM, 10-bit
  TCCR1B |= (1<<WGM12); // Fast PWM, 10-bit
  TCCR1B |= (0<<WGM13); // Fast PWM, 10-bit
  TCCR1B |= (0<<CS12); // clkI/O/1 (No prescaling)
  TCCR1B |= (0<<CS11); // clkI/O/1 (No prescaling)
  TCCR1B |= (1<<CS10); // clkI/O/1 (No prescaling)

  TCNT1H = 0x00;
  TCNT1L = 0xC7; // 199 + 1 ==> 4MHz / 1 * (1 + 199) ==> 20kHz

  OCR1AH = 0x00;
  OCR1AL = 0xA0;
  OCR1BH = 0x00;
  OCR1BL = 0xA0;
}

Ich messe 3,9 kHz. So ein Mist...
Gast #1349631
Lesenswert?

Da du mit einem PWM-Signal arbeitest darfst du nicht verwechseln, dass 
du hier die Einschaltlänge einstellst und nicht die häufigkeit wie oft 
An- und Ausgeschlatet wird.
Musste auch mal eine Frequenz von 40 kHz erzeugen ich habe dies dann 
über den Compare Output Mode and Waveform Generation gemacht.
Im Datenblatt vom Atmel ist da auch eine Formel zufinden mit der man 
sich die Frequenz errechnen kann und dann dementsprechend die Werte dazu 
einstellt.
Ich hoffe ich könnte dir damit helfen.

Grüße
#1349649
Lesenswert?

TCCR1A |= (1<<WGM11); // Fast PWM, 10-bit
  TCCR1A |= (1<<WGM10); // Fast PWM, 10-bit
  TCCR1B |= (1<<WGM12); // Fast PWM, 10-bit
  TCCR1B |= (0<<WGM13); // Fast PWM, 10-bit


Was ist daran so schwer zu verstehen, dass du in der Tabelle der PWM 
Modi einen Modus brauchst, bei dem der TOP Wert keine Konstante ist, 
sondern über ein Register festgelegt werden kann.

Du hast hier einen Fast-PWM MOdus mit 10 Bit eingestellt und laut 
Datenblatt ist der TOP Wert dafür 0x03FF, also dezimal 1023

4000000 / 1023 = 3910 Hz

Passt schon wieder auffallend.

(PS: Lass das TCNT Register in Ruhe. Darin zählt der Timer. Aber 
logischerweise kann das nicht die Steuerung dafür sein, wann der Timer 
auf 0 zurückgesetzt wird)

Tabelle 16-5
Modus 14 oder Modus 15 würden dir erlauben in ICR1 bzw. OCR1A 
festzulegen, wie weit der Timer (im Register TCNT1) zählen soll, ehe er 
wieder bei 0 beginnt.
OP #1349666
Lesenswert?

jetzt gehts, super danke!!!

void pwm(void){
  TCCR1A |= (1<<COM1A1); // Clear OC1A/OC1B on compare match when 
up-counting
  TCCR1A |= (1<<COM1B1); // Clear OC1A/OC1B on compare match when 
up-counting
  TCCR1A |= (0<<COM1A0); // Clear OC1A/OC1B on compare match when 
up-counting
  TCCR1A |= (0<<COM1B0); // Clear OC1A/OC1B on compare match when 
up-counting
  TCCR1A |= (0<<WGM11); // Phase and Frequency Correct PWM Mode
  TCCR1A |= (0<<WGM10); // Phase and Frequency Correct PWM Mode
  TCCR1B |= (0<<WGM12); // Phase and Frequency Correct PWM Mode
  TCCR1B |= (1<<WGM13); // Phase and Frequency Correct PWM Mode
  TCCR1B |= (0<<CS12); // clkI/O/1 (No prescaling)
  TCCR1B |= (0<<CS11); // clkI/O/1 (No prescaling)
  TCCR1B |= (1<<CS10); // clkI/O/1 (No prescaling)

  ICR1 = 0x64; // 4MHz / 2  1  100) ==> 20kHz

  OCR1AH = 0x00;
  OCR1AL = 0x43; // duty cycle
}

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