Hallo mitsammen. Ich hoffe ich nerve nicht mit meiner Fragerei, aber ich habe Probleme damit, die 3 PWM Kanäle des Atmega8 zu nutzen. Was ich bisher habe: Um die PWM zu nutzen, sind die Bits WGM10, WGM11, WGM12, WGM13 zuständig. Und hier schon die erste Frage: * Die Bits 10,11 sind im TCCR1A, die Bits 12,13 im TCCR2A. Ich würde gerne den 8bit - Modus nutzen (0...255), also muss: WGM10 -> 0 WGM11 -> 1 WGM12 -> 0 WGM13 -> 0 Nur nun meine Frage: Wohin muss ich denn dann den Wert schreiben, mit welchem verglichen wird - OCR1A?, OCR1B? Das wär dann wohl der erste PWM Kanal. Für den 2ten PWM Kanal ist wohl TCCR2 zuständig. D.h. WGM20 -> 1 WGM21 -> 0 -> Ebenfalls wieder eine 8bit PWM Und wieder die Frage - Wohin muss ich den wert schreiben und an welchem Pin erhalte ich das Ausgangssignal? OCR2? Und die dritte Frage: WO ist der 3te Kanal? Ein WGM3x finde ich nicht .. ebensowenig wie ein WGM0x Ich danke euch für eure Hilfe :)
Du hast doch gerade 3 PWM-Kanäle aufgezählt: OCR1A OCR1B und OCR2 Und vermutlich kommen die Vergleichswerte auch in die OC-Register (output compare register...). Bei OCR1A und OCR1B wird für beide Timer1 als Zeitbasis genommen. Für OCR2 ist die Basis Timer2.
Oh mein Gott. Irgendwie muss ich blind gewesen sein :) Mich hat das TCCR1x komplett irritiert. Heißt das, dass OCR1A und OCR1B immer im gleichen Modus laufen (Sprich: 8Bit, ..) auch wenn ich nur das TCCR1A/B dementsprechend nur einmal setze? Das heisst OC1A, OC1B und OC2 sind meine Ausgänge? Bin noch recht neu bei der ganzen Sache - Danke mal für deinen Input :)
du musst auch noch die COM1Ax und COM1Bx Register setzen - sonst kommt nix. Für Phase correct PWM (8,9 oder 10 Bit) würde ich folgendes nehmen: WGM13: 1 z.B. 8 Bit Phase correct PWM WGM12: 0 WGM11: 0 WGM10: 0 COM1A1: 1 Ausgabe an OC1A und OC1B COM1A0: 0 hochzählen:zurücksetzen COM1B1: 1 runterzählen: setzen COM1B0: 0 Wenn du dann in OCR1AL "255" reinschreibst bekommst du am Pin OC1A 5V, bei "0" 0V - an OC1B kannst du OCR1BL ausgeben.
die WGM-Werte die du oben beschrieben hast sind nach meinem Datenblatt für 9-Bit PWM
so .. die WGM habe ich geändert. Im Datenblatt des atmega8 muss WGM10 = 1 sein, der Rest = 0 für eine 8bit PWM. Ich habe jetzt: ---snip--- #include <avr/io.h> #include <stdint.h> int main(void) { // Set 8 bit Phase correct PWM Mode for channel 1 + 2(A/B) TCCR1A |= (1 << WGM10); // 8bit Phase correct CH1 TCCR1A &= ~(1 << WGM11); // 8bit Phase correct CH1 TCCR1B &= ~(1 << WGM12); // 8bit Phase correct CH2 TCCR1B &= ~(1 << WGM13); // 8bit Phase correct CH2 // Clock select channel 1+2 TCCR1B |= (1 << CS10); TCCR1B &= ~(1 << CS11); // Connect output Pin channel 1 TCCR1A &= ~(1 << COM1A0); TCCR1A |= (1 << COM1A1); // Connect output Pin channel 2 TCCR1A &= ~(1 << COM1B0); TCCR1A |= (1 << COM1B1); // Set 8 bit phase correct PWM Mode for channel 3 TCCR2 |= (1 << WGM20); TCCR2 &= ~(1 << WGM21); // Clock select channel 3 TCCR2 |= (1 << CS20); TCCR2 &= ~(1 << CS21); // Connect output Pin channel 3 TCCR2 &= ~(1 << COM20); TCCR2 |= (1 << COM21); // Now the values can be put into OCR1A, OCR1B, OCR2 OCR1AL = 0; OCR1BL = 255; OCR2 = 126; while(1); } ---snip--- Aber noch immer nix am Pin :(
Hi! Setze mal die entsprechenden Ports als Ausgang....dadrüber bin ich eben auch gerade gestolpert.... Habe aber auch ein Problem mit atmega8 und PWM: Laut PDF soll er 16 Bit PWM mit Timer1 können, also 2 PWM-Kanäle (OCR1A und OCR1B) mit je 16 Bit PWM. Ich bekomme nur 10 Bit PWM hin. Gruß Kersten
So, bei mir klappts jetzt: //Pins als Ausgang gesetzt TCCR1A |= _BV(COM1A1) | _BV(COM1B1); // Eigenschaften der Portpins TCCR1A |= _BV(WGM11); // 16 Bit Fast PWM, TOP ist ICR1: TCCR1B |= _BV(WGM12); TCCR1B |= _BV(WGM13); ICR1H = 0xFF; //Top = 0xFFFF; ICR1L = 0xFF; //Normalerweise über ein TEMP-Register schreiben, aber da der Timer noch nicht läuft sollte das nicht nötig sein TCCR1B |= _BV(CS10); // kein Prescaler und Timer starten OCR1A = 0xFFFF; //5V OCR1B = 0x7FFF; //die Hälfte @Tom: Was hat es sich denn mit OCR1AL und OCR1AH auf sich? Erscheint logisch aber steht nirgendwo im Datenblatt. Ich verwende einfach nur OCR1A/B und es klappt. Kersten
Im Datenblatt steht auf Seite 79, dass man bei den 16 bit Registern erst die das high byte beschrieben werden muss, bevor das low byte geschrieben wird. Gilt allerdings auch nur bei assembler. Wenn ihr C programmiert, macht das der Compiler selbstständig. Deswegen geht das auch wenn man direkt OCR1A/B beschreibt.
@Sebastian: Was soll das denn bitteschön wieder? Wenn die das nach zwei Jahren nicht rausgefunden haben, nützt es jetzt auch nichts mehr!
@Johannes M. (johnny-m) es gibt immer wieder Menschen denen hilft es trotzdem weiter, egal wie alt der Beitrag ist. @Sebastian: Danke ! Gruß,
Kersten D. schrieb: > So, bei mir klappts jetzt: > > //Pins als Ausgang gesetzt > TCCR1A |= _BV(COM1A1) | _BV(COM1B1); // Eigenschaften der Portpins > > TCCR1A |= _BV(WGM11); // 16 Bit Fast PWM, TOP ist ICR1: > TCCR1B |= _BV(WGM12); > TCCR1B |= _BV(WGM13); > > ICR1H = 0xFF; //Top = 0xFFFF; > ICR1L = 0xFF; //Normalerweise über ein TEMP-Register schreiben, aber da > der Timer noch nicht läuft sollte das nicht nötig sein > > TCCR1B |= _BV(CS10); // kein Prescaler und Timer starten > > OCR1A = 0xFFFF; //5V > OCR1B = 0x7FFF; //die Hälfte Hi, ich hab nur mittel viel Ahnung: Wenn ich den Code in eine int main(void) { } einfüge, müsste doch am Port OC1A bzw. -B eine LED Leuchten, ohne dass ich etwas dem Code hinzufügen muss (etwa eine while Schleife) oder fehlt da noch etwas? Danke und sorry, dass ich hier die Totenruhe störe ;)
Julian T. schrieb: > oder > fehlt da noch etwas? Bin jetzt nicht über den ganzen Code gegangen, aber du musst natürlich noch die Portpins für OC1A und OC1B auf Ausgang setzen. Das wären beim Mega8 PB1 und PB2.
Habe mir gerade auch den PWM via Timer/Counter im Datenblatt angesehen und den Code minimal angepasst, so dass er direkt lauffähig ist. Vielleicht hilft es ja jemandem. An Pin 15/16 sollte je eine LED mit Vorwiderstand, schon geht es los:
1 | // Dieses Makro verwende ich nicht mehr, hilft vielleicht den Rest des Threads zu verstehen
|
2 | //#define _BV(a) ((1 << a))
|
3 | // Mein AtMega8 läuft mit 4MHz
|
4 | #define F_CPU 4000000UL
|
5 | // Wartezeit in der Schleife auf 5us
|
6 | #define INTERVALL 5UL
|
7 | // Minimalwert 1000h
|
8 | #define MINVALPWM 0x1000
|
9 | // IO-Makros
|
10 | #include <avr/io.h> |
11 | // hier gibt es die tollen delay-Funktionen
|
12 | #include <util/delay.h> |
13 | |
14 | int main(void) |
15 | {
|
16 | DDRB |= (1<<DDB1); //Pin 15 ist ein Ausgang |
17 | DDRB |= (1<<DDB2); //Pin 16 ist ein Ausgang |
18 | /* Im folgenden wird die Pulsweitenmodulation für Timer/Counter1 eingestellt
|
19 | wir wollen eine schnelle Pulsweitenmodulation, Maximalwert (Top) in ICR1*/
|
20 | TCCR1A |= (1<<(COM1A1)) | (1<<(COM1B1)); // OC1A und OC1B beim Raufzählen an (bezieht sich auf den internen PWM) |
21 | TCCR1A |= (1<<(WGM11)); // Timer/Counter1 Control Register A - Waveform Generator Modus 11 |
22 | TCCR1B |= (1<<(WGM12)); // Timer/Counter1 Control Register B - Waveform Generator Modus 12 |
23 | TCCR1B |= (1<<(WGM13)); // Timer/Counter1 Control Register B - Waveform Generator Modus 13 |
24 | ICR1 = 0xFFFF; //ICR1, alle Bits setzen |
25 | TCCR1B |= (1<<(CS10)); // kein Prescaler (clkio wird 1:1 vom IC-Takt übernommen), Timer starten |
26 | |
27 | uint_fast16_t n = MINVALPWM; // 16-Bit-Variable für die Dimmschleife |
28 | while (1) |
29 | {
|
30 | OCR1A = 0xFFFF; //5V an Pin 15 |
31 | for (;n<0xffff;n++) //von MINVALPWM bis 2^16 raufzählen |
32 | {
|
33 | OCR1B = n; // Intensität setzen |
34 | _delay_us(INTERVALL); //5us Pause |
35 | }
|
36 | OCR1A = 0; //0V an Pin 15 |
37 | for (;n>MINVALPWM;n--) //von 2^16 bis MINVALPWM runterzählen |
38 | {
|
39 | OCR1B = n; // Intensität setzen |
40 | _delay_us(INTERVALL); //5us Pause |
41 | }
|
42 | }
|
43 | }
|
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.