AVR PWM

From RoboWiki
Revision as of 13:38, 15 January 2008 by Balogh (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

PWM (Pulsweitenmodulation)

Wir kommen nun zu einem Thema, welches in aller Munde ist, aber viele Anwender verstehen nicht ganz, wie PWM eigentlich funktioniert.

Wie wir alle wissen, ist ein Mikrocontroller ein rein digitales Bauteil. Definieren wir einen Pin als Ausgang, dann können wir diesen Ausgang entweder auf HIGH setzen, worauf am Ausgang die Versorgungsspannung Vcc anliegt, oder aber wir setzen den Ausgang auf LOW, wonach dann 0V am Ausgang liegt. Was passiert aber nun, wenn wir periodisch mit einer festen Frequenz zwischen HIGH und LOW umschalten? - Richtig, wir erhalten eine Rechteckspannung, wie die folgende Abbildung zeigt:

File:PWM Theorie 1.gif

Diese Rechteckspannung hat nun einen arithmetischen Mittelwert, der je nach Pulsbreite kleiner oder größer ist.

File:PWM Theorie 2.gif

Wenn wir nun diese pulsierende Ausgangsspannung noch über ein RC-Glied filtern/"glätten", dann haben wir schon eine entsprechende Gleichspannung erzeugt.

Mit den AVRs können wir direkt PWM-Signale erzeugen. Dazu dient der 16-Bit Zähler, welcher im sogenannten PWM-Modus betrieben werden kann.

Hinweis:

In den folgenden Überlegungen wird als Controller der 90S2313 vorausgesetzt. Die Theorie ist bei anderen AVR-Controllern vergleichbar, die Pinbelegung allerdings nicht unbedingt, weshalb ein Blick ins entsprechende Datenblatt dringend angeraten wird.

Um den PWM-Modus zu aktivieren, müssen im Timer/Counter1 Control Register A TCCR1A die Pulsweiten-Modulatorbits PWM10 bzw. PWM11 entsprechend nachfolgender Tabelle gesetzt werden:

PWM11 PWM10 Bedeutung
0 0 PWM-Modus des Timers ist nicht aktiv.
0 1 8-Bit PWM.
1 0 9-Bit PWM.
1 1 10-Bit PWM.

Der Timer/Counter zählt nun permanent von 0 bis zur Obergrenze und wieder zurück, er wird also als sogenannter Auf-/Ab Zähler betrieben. Die Obergrenze hängt davon ab, ob wir mit 8, 9 oder 10-Bit PWM arbeiten wollen:

Auflösung Obergrenze Frequenz
8 255 fTC1 / 510
9 511 fTC1 / 1022
10 1023 fTC1 / 2046

Zusätzlich muss mit den Bits COM1A1 und COM1A0 desselben Registers die gewünschte Ausgabeart des Signals definiert werden:

COM1A1 COM1A0 Bedeutung
0 0 Keine Wirkung, Pin wird nicht geschaltet.
0 1 Keine Wirkung, Pin wird nicht geschaltet.
1 0 Nicht invertierende PWM.

Der Ausgangspin wird gelöscht beim Hochzählen und gesetzt beim Herunterzählen.

1 1 Invertierende PWM.

Der Ausgangspin wird gelöscht beim Herunterzählen und gesetzt beim Hochzählen.

Der entsprechende Befehl, um beispielsweise den Timer/Counter als nicht invertierenden 10-Bit PWM zu verwenden, heißt dann:

alte Schreibweise (PWMxx wird nicht mehr akzeptiert) <c> TCCR1A = (1<<PWM11)|(1<<PWM10)|(1<<COM1A1); </c> neue Schreibweise <c> TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1); </c>

Damit der Timer/Counter überhaupt läuft, müssen wir im Control Register B TCCR1B noch den gewünschten Takt (Vorteiler) einstellen und somit auch die Frequenz des PWM-Signals bestimmen.

CS12 CS11 CS10 Bedeutung
0 0 0 Stop. Der Timer/Counter wird gestoppt.
0 0 1 CK
0 1 0 CK / 8
0 1 1 CK / 64
1 0 0 CK / 256
1 0 1 CK / 1024
1 1 0 Externer Pin 1, negative Flanke
1 1 1 Externer Pin 1, positive Flanke

Also um einen Takt von CK / 1024 zu generieren, verwenden wir folgenden Befehl:

<c> TCCR1B = (1<<CS12) | (1<<CS10); </c>

Jetzt muss nur noch der Vergleichswert festgelegt werden. Diesen schreiben wir in das 16-Bit Timer/Counter Output Compare Register OCR1A.

<c> OCR1A = xxx; </c>

Die folgende Grafik soll den Zusammenhang zwischen dem Vergleichswert und dem generierten PWM-Signal aufzeigen.

File:PWM Theorie 3.gif

File:PWM Theorie 4.gif

Ach ja, fast hätte ich's vergessen. Das generierte PWM-Signal wird am Output Compare Pin OC1 des Timers ausgegeben und leider können wir deshalb auch beim AT90S2313 nur ein einzelnes PWM-Signal mit dieser Methode generieren. Andere AVR-Typen verfügen über bis zu vier PWM-Ausgänge. Zu beachten ist außerdem, das wenn der OC Pin aktiviert ist, er nichtmehr wie üblich funktioniert und z.B. nicht einfach über PORTx ausgelesen werden kann.