Versuche mich gerade an einer PWM Led Steuerung auf einem Atmega 324PB.
Hier habe ich eine LED an PB7 (OC4B)
Wie schaffe ich es, dass ich mir die PWM auf diesen PIN (OC4B und nicht
OC4A) gebe.
Folgenden Code verwende ich:
1
DDRB|=(1<<PB7)//Ausgang aktivieren
2
3
// PWM für blaue LED
4
5
TCCR4A|=(1<<COM4A1);// clear OC4A on compare match
6
TCCR4A|=(1<<WGM43)|(1<<WGM42)|(1<<WGM41)|(1<<WGM40);// Fast PWM (m. 15)
Danke Stefan,
aber irgendwie bin ich zu blöd dafür. Für die beiden anderen LEDs hat es
geklappt. Aber die blaue LED an PB7 (OC4B) will nicht. Hängt es
vielleicht damit zusammen, das beim Atmega324PB auch OC3B auf auf PB7
ist und sich das was gegenseitig blockiert. Bitte um Hilfe weil ich
einfach nicht weiterkomme.
1
// PWM für rote LED an PB6 (OC3A)
2
3
TCCR3A|=(1<<COM3A1);// clear OC3A on compare match
4
TCCR3A|=(1<<WGM33)|(1<<WGM32)|(1<<WGM31)|(1<<WGM30);// Fast PWM (mode 15), zählen bis OCR3A
5
6
TCCR3B|=(1<<CS30);// Kein Vorteiler
7
8
OCR3A=30000;
9
10
11
// PWM für grüne LED an PD5 (OC1A)
12
13
TCCR1A|=(1<<COM1A1);// clear OC1A on compare match
14
TCCR1A|=(1<<WGM13)|(1<<WGM12)|(1<<WGM11)|(1<<WGM10);// Fast PWM (mode 15), zählen bis OCR1A
15
16
TCCR1B|=(1<<CS10);// Kein Vorteiler
17
18
OCR1A=30000;
19
20
21
22
// PWM für blaue LED an PB7 (OC4B)
23
24
TCCR4A|=(1<<COM4B1);// clear OC4B on compare match
25
TCCR4A|=(1<<WGM43)|(1<<WGM42)|(1<<WGM41)|(1<<WGM40);// Fast PWM (mode 15), zählen bis OCR4A
H.Joachim S. schrieb:> Jakob schrieb:>>> TCCR4A |= (1<<WGM43)|(1<<WGM42) |(1<<WGM41) |(1<<WGM40); // Fast PWM> WGM42 und 43 liegen in TCCR4B
Analog dazu auch WGM12/13 und WGM32/33.
Jakob schrieb:> TCCR4A |= (1<<COM4B1); // clear OC4B on compare match
Der Kommentar gilt für für nicht-PWM Modus. Im PWM Modus ist es "Clear
OC4B on Compare Match, set OC4B at BOTTOM (non-inverting mode)"
Ein falscher Kommentar kann schädlicher sein, als kein Kommentar.
> ... // Fast PWM (mode 15), Zählen bis OCR4A> OCR4B = 30000;
Dann musst du auch OCR4A auf einen Wert > 30000 ein stellen, sonst zählt
er nur von 0 bis 0.
Im Datenblatt steht in der Tabelle zur FastPWM (Mode 15, Seite 169), das
dann TOP = OCR4A sei. Daher dachte ich, OCR4A statt OCR4B vorgeben zu
müssen. Nun ja, ändert ja eh nicht daran das keine PWM erzeugt wird.
OCR4A gibt den TOP-Wert des Zählers vor, also die gesamte Dauer einer
Periode.
OCR4B stellt die Pulsbreite des PWM Signals ein.
OCR4B muss < OCR4A sein, damit du Impulse bekommst.
Der 324PB hatte auch ein (oder mehrere) Probleme mit den OC-Ausgängen,
bin ich auch schon mal drüber gestolpert. Steht hier irgendwo im Forum.
Microchip fand das nicht buggy genug um es wenigstens in die errata
aufzunehmen. Ausser Gelaber vom Inder kam da gar nichts. Keine Ahnung ob
das jetzt auch dein Problem ist, gut möglich. Ich habe keine Lust das
wieder rauszusuchen, war frustrierend genug.
Jakob, vielleicht bis du für heute ermüdet.
Jakob schrieb:> TCCR4A |= (1<<COM4B1) | (1<<COM4B0); // Clear OC4A/OC4B on Compare> Match, set OC4A/OC4B at BOTTOM (non-inverting mode)
Hier stimmt schon wieder der Kommentar nicht. Dieses mal hast du auf den
"inverting mode" gewechselt, warum eigentlich?
Wahrscheinlich ist irgendwo noch ein Fehler verborgen den ich gerade
auch nicht erkenne. Läuft der Zähler überhaupt?
Kann es sein, dass du gleichzeitig eine andere alternative Funktion auf
dem selben Pin aktiviert hast (SCK0, OC3B)?
Da gibt es einen interessanten Satz im Datenblatt "For OC3B or OC4B when
not using the Output Compare Modulator, PORTD2 must also be set in
order to enable the output."
Oder du aktivierst halt diesen Modulator, siehe Kapitel 21 im
Datenblatt.
Hat der Chip noch mehr solche Sonderlocken? Ist ja schlimmer als bei ST!
Ich geb dann auch mal auf. Was hate denn nun PORTD2 mit OC3B und OC4B zu
schaffen, die liegen beide mit SCK0 auf PORTB7.
Auf PORTD2 liegt INT0, den ich aber als Eingang brauche.
von
https://www.avrfreaks.net/forum/need-generate-pwm-waveform-0c3b-atmega328pb
"I also verified that the Output Compare Modulator issue didn't get
fixed. It is supposed to be enabled only if OC3B and OC4B are enabled
but it appears that it is enabled if either OC3B or OC4B are enabled.
As a consequence of this error, you must write a 1 to bit 2 of PORTD in
order to get PWM output on PD2 from either Timer3 or Timer4. I suspect
that the same workaround would need to be used any time you want OC3B or
OC4B output on PD2. If you're actually using the Output Compare
Modulator you'd write a 0 or a 1 to bit 2 of PORTD depending on whether
you want AND or OR modulation."
Mit dem PORTD2 wird ein Druckfehler sein (auf dem 328 liegt OC3B/OC4B
auf PORTD2), schreib mal eine 1 an PORTB7:
PORTB |= (1<<PB7);
siehe auch:
https://github.com/watterott/ATmega328PB-Testing/issues/29#issuecomment-364785135
Alexander S. schrieb:> PORTB |= (1<<PB7);
Danke euch, das hat das Rätsel endlich gelöst. Läuft endlich.
Nochmals Danke, das hat mich jetzt viele Stunden und Nerven gekostet.
Leider noch nicht so ganz. PWM an OC4B fuktioniert nun super,
nur leider die grüne und rote LED nicht mehr.
Kann langsam auch kaum noch erkennen was ich da eigentlich tippe. Aber
vielleicht könnte nochmal jemand raufschauen was ich da jetzt versaut
habe.
1
/////////////////PWM LEDs/////////////////
2
3
PORTB|=(1<<7);
4
5
// PWM für rote LED an PB6 (OC3A)
6
7
TCCR3A|=(1<<COM3A1);
8
TCCR3A|=(1<<WGM31)|(1<<WGM30);
9
10
TCCR3B|=(1<<WGM33)|(1<<WGM32)|(1<<CS30);
11
12
OCR3A=1000;
13
OCR3B=0;
14
15
16
17
18
19
// PWM für grüne LED an PD5 (OC1A)
20
21
TCCR1A|=(1<<COM1A1);
22
TCCR1A|=(1<<WGM11)|(1<<WGM10);
23
24
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
25
26
OCR1A=1000;
27
OCR1B=0;
28
29
30
31
32
// PWM für blaue LED an PB7 (OC4B)
33
TCCR4A|=(1<<COM4B1);
34
TCCR4A|=(1<<WGM41)|(1<<WGM40);
35
36
TCCR4B|=(1<<WGM43)|(1<<WGM42)|(1<<CS40);
37
38
OCR4A=1000;
39
OCR4B=0;
40
41
42
/////////////////////////////////////////////
In der while wird testweise folgendes ausgeführt:
1
OCR1B++;//grüne LED
2
OCR3B++;//rote LED;
3
OCR4B++;//blaue LED
4
_delay_ms(10);
... das "Aufdimmen" klappt jetzt leider nur noch bei der blauen LED.