Hi, versuche gerade pwm zu verstehen und zu benutzen. Folgender code soll auf einem mega32 ein step-up licht erzeugen: #include <avr/io.h> #include <avr/delay.h> int main (void) { DDRB=0xff; PORTB=0x00; int i; TCCR0 = (_BV(WGM00) | _BV(COM01) | _BV(COM00) | _BV(CS00)); while(1) {for (i=0;i<255;i=i+1) {OCR0=i; _delay_loop_2(20000);}} } Ich habe allerdings einen mega8. Ich weiß dass ich zum beispiel den Ausgang ändern muss, weil es OCR0 beim Mega8 nicht gibt aber wie muss ich den Timer einstellen? Vielen Dank!
Statt Timer0 mußt du den Timer2 nehmen. Prinzipiell sieht die Konfiguration gleich aus, nur daß halt überall die Null hinter dem Namen durch eine 2 ersetzt werden muß (TCCR0 -> TCCR2, WGM00 -> WGM20, OCR0 -> OCR2 u.s.w.)
danke das klappt jetzt, nur warum? ist das nur ne namenssache oder gibt es da noch einen unterschied?
> nur warum?
Das übliche:
Besorg die bei www.atmel.com die Datenblätter der beiden µC
und vergleiche selbst.
Das ist übrigens genau das, was ich getan habe, um die Antwort zu geben. (Naja, nicht ganz. Ich hatte die Datenblätter schon auf der Platte)
so hab jetzt ein bisschen weiter studiert und bin soweit gekommen: #include <avr/io.h> #include <avr/delay.h> int DATA[] = { 0xFF, 0x3C, 0x00, 0xFF, 0x3C, 0x00, 0xFF, 0x3C, 0x00, 0xFF, 0x3C, 0x00, 0xFF, 0x3C, 0x00, 0xFF}; int main () { DDRB=0xff; PORTB=0x00; int i=0; TCCR2 = (_BV(WGM21) | _BV(WGM20) | _BV(COM21) | _BV(COM20) | _BV(CS20)); while(1) { for (i=0;i<15;i++) OCR2=255-DATA[i]; } return 0; } an PB.3 hab ich einen Piezo gehängt und der erzeugt einen sehr hohen ton (ca. 1200Hz?). Nach meiner einstellung in TCCR2 sollte ich ja genau den Takt der CPU Clock erzeugen oder? Welche Frequenz erzeuge ich denn hier? (mein quartz hat 16.000Mhz). Ihr seht vielleicht, dass ich schon irgendwelche daten ausgeben will! Mein Ziel ist es irgendwie eine Wave datei mal abzuspielen ;). Dabei lese ich immer wieder dass man "einfach" die daten am PWM ausgibt und dann mit der richtig frequenz abspielt. Das muss ich aber erstmal richtig verstehen.
Der Timer läuft einmal alle 256 Schritte über, also mit einer Frequenz von 62,5 kHz. Das ist die Frequenz deiner PWM. Dein Programm rennt allerdings arg schnell durch. Deine Schleife ändert den Wert für OCR2 so schnell sie kann, also ziemlich oft, bevor er überhaupt gebraucht wird. Der Ton, den du hörst, ist möglicherweise irgenein Interferenzmuster aus deiner PWM-Frequenz und der Frequenz, mit der du OCR2 änderst. Du solltest vielleicht den OCR2-Wert besser im Timer-Overflow-Interrupt ändern, damit er genau einmal pro PWM-Durchlauf geändert wird.
stimmt daran hab ich noch gar nicht gedacht! ich hab das jetzt mal mit dem interrupt versucht aber ich glaub das ist nicht so ganz richtig oder? Welchen muss ich genau nehmen. SIGNAL (SIG_OUTPUT_COMPARE2) { for (i=0;i<15;i++) OCR2=255-DATA[i]; } int main () { DDRB=0xff; PORTB=0x00; TCCR2 = (_BV(WGM21) | _BV(WGM20) | _BV(COM21) | _BV(COM20) | _BV(CS20)); sei (); for(;;); return 0; } so bekomme ich gar keinen ton mehr.
Der Vektor ist der richtige, aber du schaltest nirgends den Output-Compare-Interrupt ein. Außerdem rennt die Schleife immer noch mit maximaler Geschwindigkeit durch, aber halt nur noch einmal pro Timer-Durchlauf. Du darfst bei jedem Interrupt nur einen Wert an OCR2 ausgeben.
Ach, moment. Du solltest nicht den output-compare-Interrupt nehmen, sondern den für Overflow.
so nächster tag ;), ich hab das jetzt so aufgebaut:
1 | #include <avr/io.h> |
2 | #include <avr/delay.h> |
3 | #include <avr/interrupt.h> |
4 | |
5 | #define FREQ 440 |
6 | #define TIMER 255 - (FREQ/128) |
7 | |
8 | int DATA[] = { 0xFF, 0x3C, 0x00, 0xFF, 0x3C, 0x00, 0xFF, 0x3C, |
9 | 0x00, 0xFF, 0x3C, 0x00, 0xFF, 0x3C, 0x00, 0xFF}; |
10 | |
11 | int i=0; |
12 | |
13 | SIGNAL (SIG_OVERFLOW2) { |
14 | if(i>15) |
15 | i=0; |
16 | |
17 | OCR2=255-DATA[i]; |
18 | i++; |
19 | TCNT2 = TIMER; |
20 | } |
21 | |
22 | int main () |
23 | { |
24 | DDRB=0xff; |
25 | PORTB=0x00; |
26 | |
27 | TCCR2 = (_BV(WGM21) | _BV(WGM20) | _BV(COM21) | _BV(COM20) | |
28 | _BV(CS20)); |
29 | TIMSK |= (1 << TOIE2); |
30 | TCNT2 = 0; |
31 | |
32 | sei (); |
33 | |
34 | for(;;) { |
35 | } |
36 | |
37 | return 0; |
38 | } |
aber der rennt durch den overflow interrupt durch. Was mach ich denn noch falsch? Ich möchte meine daten mit einer genauen frequenz abspielen. vielen dank für eure antworten!
ich hab das ganze jetzt wie im anhang zu sehen gelöst. Irgendwie find ich das aber etwas seltsam. Mit TCNT2 bzw. OVERFLOW2 hab ich es nicht hinbekommen. Ich denke jetzt ist es relativ genau oder?
Ich hab das Gefühl, daß du noch nicht ganz verstanden hast, wozu die PWM da ist. Mir ist nicht klar, ob du die eigentlich überhaupt haben willst. Warum verstellst du auf einmal TCNT1 in der Interrupt-Routine? Damit verstellst du die PWM-Frequenz, statt nur die Pulsweite. Also: Willst du nun einfach nur ein rechteckförmiges Signal mit bestimmter Frequenz haben oder eine PWM, über die du die Wellenform auch bestimmen kannst? Momentan macht dein Programm ein Mischmasch aus beidem.
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.