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 }
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 ); |
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
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
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 )
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
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...
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.