Forum: Mikrocontroller und Digitale Elektronik PWM auf Timer/Counter0 Probleme


von Hans R. (hansrichter)


Lesenswert?

Würde gerne eine PWM auf PD5 (Atemga168) mit Timer/Counter0 erzeugen, 
aber wenn ich die Funktion PWM_init aufrufe, tut sich an PD5 leider 
nichts.

Was mache ich hier falsch?

// Timer/Counter 0 mit PWM initialisieren und auf PD5 ausgeben
void PWM_setup(void)
{


DDRD |= (1<<PD5); //PWM PIN PD5 als Ausgang setzen

TCCR0A = (1 << COM0B1) | (1 << WGM00);
TCCR0B = (1 << WGM02) | (1 << CS00);  //Vorteier=1
OCR0A = 125;//Duty-Cycle              //OCR0A als TOP Wert


}

Wäre jemand so nett, mir mal auf die Sprünge zu helfen?

von Stefan F. (Gast)


Lesenswert?

PD5 hängt vermutlich an OCR0B. Wenn du da keinen Wert reinschreibt, hast 
du kein PWM Signal.

von Hans R. (hansrichter)


Lesenswert?

Ja hängt an OCROB.

Aber anders formuliert:
Ich würde dem Timer gerne einen Topwert zuweisen und mit OCRA festlegen, 
bis wo gezählt wird, um einen Duty-Cycle zu erhalten.

Da stelle ich mich scheinbar zu blöd an.


Mit Timer1 hatte ich es folgendermaßen hinbekommen:


DDRB |= (1<<PB1);  //PWM PIN als Ausgang setzen

TCCR1B = (1<<WGM13);  //PWM, Phasen- und Frequnezrichtig mit ICR1 als 
TOP

ICR1 = 500; //Topwert bis wo gezählt wird. 500 für 20kHz PWM
OCR1A = 250;//50% OCR1A gibt den Duty-Cylce vor (ICR1 für 100%)
TCCR1B |= (1<<CS10);  //Vorteiler = 1
TCCR1A = (1<<COM1A1);  //Nicht invertierende PWM auf OC1A (PB1) ausgeben

Würde im Grunde gerne gleiches mit Timer0 hinbekommen, auch wenn dieser 
nur 8Bit hat.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Hans R. schrieb:
> Da stelle ich mich scheinbar zu blöd an.

Nö, du hast nur Stefans Kommentar nicht verstanden. Wenn du OC0A mit dem 
Register OCR0A benutzen willst, dann solltest du den Ausgang auf PD6 
aktivieren und da das Signal abgreifen.
Wenn du jedoch unbedingt an PD5 PWM brauchst, dann stellst du die COMnn 
Bits für OC0B ein und setzt die PWM über OCR0B.

von Hans R. (hansrichter)


Lesenswert?

Tut mir leid, wenn ich mich so blöd anstelle, aber ich bekomme es nicht 
hin. Brauche die PWM zwingend auf PD5.

Immerhin,

eine PWM mit 50% Duty-Cycle kommt, wenn ich folgendes mache (wobei das 
natürlich wohl nicht richtig ist)

DDRD |= (1<<PD5);              //PWM PIN PD5 als Ausgang setzen

TCCR0A = (1 << COM0B1) | (1 << WGM00);
TCCR0B = (1 << WGM02) | (1 << CS00);   //Vorteier=1
//OCR0B = 100;                         //Duty-Cycle


TCCR0A=(1<<COM0B0);

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Hey, wieso kommentierst du die wichtigste Zeile aus? Da wird doch die 
PWM auf OC0B gesetzt. Wenn OC0B auf 0 steht, bekommst du schmale 
Nadelimpulse am Ausgang. Ausserdem hast du dir Phase Correct mit TOP in 
OCR0A ausgesucht. Da musst du jetzt noch den gewünschten Maximalwert des 
Timers in OCR0A schreiben. Siehe Tabelle 15.8 im Datenblatt des Mega328 
von 5/11.

von S. Landolt (Gast)


Lesenswert?

Überhaupt betreibt er seinen ATmega168 jetzt in einem 'Reserved'-Modus.

von Hans R. (hansrichter)


Lesenswert?

Jetzt sieht es also so aus, änder allerdings nichts daran als das ich 
weiterhin 50% Duty-Cycle und nicht 25% an PD5 bekomme:

void PWM_init(void)
{
DDRD |= (1<<PD5);                       //PWM PIN PD5 als Ausgang setzen

TCCR0A = (1 << COM0B1) | (1 << WGM00);
TCCR0B = (1 << WGM02) | (1 << CS00);  //Vorteier=1
OCR0A = 200;        //TOP-Wert
OCR0B = 50;        //Duty-Cycle


TCCR0A=(1<<COM0B0);
}

von spess53 (Gast)


Lesenswert?

Hi

Du schreibst

>TCCR0A = (1 << COM0B1) | (1 << WGM00);
...
>TCCR0A=(1<<COM0B0);

MfG Spess

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

S. Landolt schrieb:
> Überhaupt betreibt er seinen ATmega168 jetzt in einem 'Reserved'-Modus.

Ursprünglich ist ja WGM00 und WGM02 gesetzt, das ist schon Mode 5.

Aber das macht der TE in der letzten Zeile zunichte:

Hans R. schrieb:
> TCCR0A=(1<<COM0B0);

Und damit hat er den o.a. 'Reserved' Mode eingestellt.
@TE: Miss mal ein bisschen, was da so passiert, klingt interessant :-)

von Hans R. (hansrichter)


Lesenswert?

Laut Datenblatt unter Waveform Generation, lege ich mit 1<<WGM02 und 
1<<WGM00 den Mode5 fest. D.h. Phasenrichtige PWM mit OCRA als TOP.

von Hans R. (hansrichter)


Lesenswert?

Maththias, dann sag mir doch bitte wie es richtig lauten müsste.

von Hans R. (hansrichter)


Lesenswert?

OK, hat sich geklärt. Die letzte Zeile war mist ;-)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Hans R. schrieb:
> OK, hat sich geklärt. Die letzte Zeile war mist ;-)

So isses. Wenn du nachträglich ein Bit in einem schon besetzten Register 
setzen willst, musst du eben verodern:
1
TCCR0A |= (1 <<COMOB0);

Siehe auch
https://www.mikrocontroller.net/articles/Bitmanipulation

von Hans Richter (Gast)


Lesenswert?

Ich hätte da doch noch eine Frage,

meiner Vorstellung nach müsste ich ja mit einem 8MHz Quarz ohne 
Vorteiler auf eine eine PWM von (8MHZ / 256) = 31,250kHz bei OCR0A=255 
kommen.




Laut Oszilloskop beträgt diese allerdings nur etwa die Hälfte 
(15784kHz).
Klar, ich kann mir OCR0A runtergehen, dann wirds schneller.

Aber wie ist der Zusammenhang?

Warum ist die volle Frequenz nicht auf meine 8Bit defiert (OCR0A=255)?

von S. Landolt (Gast)


Lesenswert?

Ist das noch der Modus 5 von oben? Wenn ja, dann mal im Datenblatt unter 
"15.7.4 Phase correct PWM mode" nachschauen, in "Figure 15-7." läuft der 
Zähler rauf & runter, ergibt den Faktor 2, oder eben die Formel mit f 
OCnxPCPWM.

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.