Johannes schrieb:
Liebe Community,
ich versuche gerade PWM bei den AVRs zu verstehen.
Bis jetzt habe ich immer nur in Arduino die analogWrite() funktion
benutzt.
Was ich bisher verstanden habe ist das Grundprinzip von PWM und dass
dies über timer realisiert wird die immer hochzählen bis zu einem
bestimmten Wert und dann den Ausgang setzten.
Genau, der Timer zählt bis zum eingestellten TOP, welches die Periodendauer vorgibt, und wenn der Timerzähler unterwegs an einem eingestellten Compare-Wert (Duty) vorbeikommt passiert irgendwas, was der Anwender konfiguriert hat. Entweder schaltet ein Pin sein Pegel um oder die ISR wir aktiv ... Bei TOP passiert auch irgendwas je nach Timerkonfig.
Meine Fragen:
- Die meisten AVRs haben aber doch nur wenige Timer/"Timer-Pins".
Wie macht es dann der Arduino, dass er zig PWM Ausgänge hat und diese so
einfach nur mit einer Funktion ansteuerbar sind?
Es werden möglichst alle Compare Ausgänge eines Timers verwendet und möglichst alle vorhandenen Timer.
Ein Timer hat in der Regel, bei den "alten" ATmegas 2 bis 3 eigene Ausgänge OCnx je Timer.
Bei den neueren Serien gibt es noch einen Splitmode, dann hat man statt 3 (16-Bit) plötzlich 6 (8-Bit) Compareausgänge zur Verfügung mit einem einzigen Timer.
Daran kannste sehen was alles hinter den Kulissen im Arduino Framework abläuft um es dem Anwender so einfach wie möglich zu machen, wenn dieser nur analogWrite() verwenden muss.
- Wie macht ihr das in der Praxis wenn ihr PWM mit einem AVR nutzt?
Jedes Mal aufwendig über diese ganzen Register oder gibts da ne
einfache, schnelle und übersichtliche Variante?
Es gibt nur die eine Möglichkeit die Register entsprechend zu konfigurieren. Das macht das Arduino Framework so und man muss es selbst auch machen. Egal wie man es macht, man muss immer die Register konfigurieren und ggf. zur Laufzeit ändern.
- Was genau macht das analogWrite()? Setzt das die Register und
alles im Hintergrund?
Genau. Das Arduino Framework konfiguriert einige Register vor, auch wenn die Hardwareeinheit in dem Moment noch nicht genutzt wird oder nie genutzt wird. Deswegen ist es bspw. wichtig bei eigener Verwendung der Timer alle Register zu nullen bevor man selbst konfiguriert. Ohne Arduino Framework sind alle Register nach Reset genullt bzw. haben die Default Einstellung laut Manual.
Mach selbst einmal folgenden Test. Lasse dir von einem Timer deiner Wahl, wovon du weißt das Pins für analogWrite verfügbar sind, alle Registerwerte ausgeben. Danach nutzt du 1x analogWrite und lässt dir erneut alle Registerwerte ausgeben.
Wenn du wissen möchtest was beim Arduino Frameworkim Hintergrund passiert, dann:
Michael B. schrieb im Beitrag #7605671:
https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring_analog.c
Liegt auch alles auf deinem Rechner im Arduino Installationsverzeichnis.