Forum: Mikrocontroller und Digitale Elektronik pwm atmega16 falsche frequenz


von Stefan Z. (derdespot)


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
}

von Karl H. (kbuchegg)


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  );

von Stefan Z. (derdespot)


Lesenswert?

wie define legt doch 200 fest oder?

von Karl H. (kbuchegg)


Lesenswert?

Stefan Z. schrieb:
> wie define legt doch 200 fest oder?

Ja und?

Definieren kann ich viel.
Aber deiner Hardware ist das ziemlich egal, was du definierst.

Datenblatt Mega16, Tabelle 17-2
Fast-PWM Mode, der Timer zählt von 0 bis 0xFF

4Mhz / 256 = 15.6 kHz

Passt auffallend

von Stefan Z. (derdespot)


Lesenswert?

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

von Karl H. (kbuchegg)


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 )

von Stefan Z. (derdespot)


Lesenswert?

ok, danke

von spess53 (Gast)


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

von Stefan Z. (derdespot)


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...

von Chridre (Gast)


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

von Karl H. (kbuchegg)


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.

von Stefan Z. (derdespot)


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
}

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.